2012-06-15 6 views
3

У меня есть следующий объект:Установка вложенного значения объекта

var object = { 
    "property1": "value1", 
    "property2": "value2", 
    "subobject": { 
     "property1": "value1", 
     "property2": "value2", 
     "subobject": { 
      "property1": "value1", 
      "property2": "value2", 
      "subobject": {... 
      } 
     } 
    } 
} 

Я пытаюсь установить один из вложенных свойств подобъектов, но вложенный уровень является динамическим.

Как я могу динамически установить одно из этих вложенных свойств, не делая что-то вроде этого: object.subobject.subobject = { ... }?

Edit: Так, чтобы быть более конкретным, я пытаюсь установить один из вложенных подобъектов, но я не знаю, какой из них каждый раз.

+0

Определение * динамический *. Как вы, кажется, на правильном пути. –

+1

У вас есть ** объект **, а не JSON, который будет обозначаться строкой. –

ответ

4

Давайте использовать рекурсию!

function setNest(obj, level, val){ 
    if(level > 0){ 
     setNest(obj.subobject, level-1, val); 
    } 
    else{ 
     obj.subobject = val; 
    } 
} 

Затем вызовите его, как:

setNest(object, 2, {a: 12}); 
+0

Вау, где мой мозг сегодня. Я не уверен на 100%, почему я не рассматривал рекурсивную функцию ... Я пытался сделать это в цикле. Спасибо за дополнительную пару глаз! –

+0

Добро пожаловать. Рекурсия может быть сложной, но она идеально подходит для таких ситуаций :-) –

+0

Я попытался реализовать решение, которое включает это, но кажется, что эта функция не обновляет значение исходного объекта. Есть предположения? –

4

Использование рекурсии - рефакторинг (спасибо Rocket HAZMAT)

Эта функция работает для меня !:

/** 
* @obj: the json object to change 
* @access: string dot separates route to value 
* @value: new valu 
*/ 
function setValue(obj,access,value){ 
    if (typeof(access)=='string'){ 
     access = access.split('.'); 
    } 
    if (access.length > 1){ 
     setValue(obj[access.shift()],access,value); 
    }else{ 
     obj[access[0]] = value; 
    } 
} 

Наличие объекта:

var jsonObject = { 
    'name' : 'pepe', 
    'links' : 
     { 
     'link1' : 'one', 
     'link2' : 'two', 
     'link3' : 
      { 
      'link31' : '3url', 
      'link32' : '3url', 
      'link33' : '3url' 
      } 
     } 
} 

Мы можем изменить значение легко с:

setValue(jsonObject,'links.link3.link32','new value!!!'); 

Благодарности

+0

Отсутствует инициализация объекта. '' 'setValue (obj [access.shift()], access, value);' '' 'должно быть' '' setValue (obj [access.shift()] = {}, access, value); '' '. –

0

Вы можете определить свои собственные методы объектов; Кроме того, я использую подчеркивание для краткости:

var _ = require('underscore'); 

// a fast get method for object, by specifying an address with depth 
Object.prototype.pick = function(addr) { 
    if (!_.isArray(addr)) return this[addr]; // if isn't array, just get normally 
    var tmpo = this; 
    while (i = addr.shift()) 
     tmpo = tmpo[i]; 
    return tmpo; 
}; 
// a fast set method for object, put value at obj[addr] 
Object.prototype.put = function(addr, val) { 
    if (!_.isArray(addr)) this[addr] = val; // if isn't array, just set normally 
    this.pick(_.initial(addr))[_.last(addr)] = val; 
}; 

Пример использования:

var obj = { 
      'foo': { 
        'bar': 0 }} 

obj.pick('foo'); // returns { bar: 0 } 
obj.pick(['foo','bar']); // returns 0 
obj.pick('foo.bar'.split('.')); // equivalent as above, returns 0 
obj.put(['foo', 'bar'], -1) // obj becomes {'foo': {'bar': -1}} 
0

Вы можете попробовать использовать Immutable.js, например так:

var immutableJsObject = Immutable.fromJS({ 
    inputs: { 
    firstDepthNumberOne: { 
     secondDepth: 'secondDepthValue' 
    }, 
    firstDepthNumberTwo: 'hello' 
    } 
}); 

var newImmutableJsObject = immutableJsObject.setIn('inputs.firstDepthNumberOne.secondDepth'.split('.'), 'newValue'); 

newImmutableJsObject.toJS(); 
Смежные вопросы