4

I have the following object:

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

I am trying to set one of the nested subobject properties, but the nested level is dynamic.

How can I dynamically set one of these nested properties without doing something like this: object.subobject.subobject = { ... }?

Edit: So to be more specific, I am trying to set one of the nested subobjects, but I won't know which one each time.

2
  • Define dynamic. As you seem to be on the right track. Commented Jun 15, 2012 at 16:44
  • 1
    You have following object, not JSON which would be quoted string. Commented Jun 15, 2012 at 16:46

4 Answers 4

7

Using recursion - refactor (thanks Rocket Hazmat)

This function works for me!:

/**
 * @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;
    }
}

Having an object:

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

We can change a value easy with:

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

Thanks

Sign up to request clarification or add additional context in comments.

1 Comment

There is a missing object initialisation. setValue(obj[access.shift()],access,value); should be setValue(obj[access.shift()] = {},access,value);.
5

Let's use recursion!

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

Then call it like:

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

7 Comments

Wow, where is my brain today. I am not 100% sure why I didn't consider a recursive function... I was trying to do it in a loop. Thanks for the extra pair of eyes!
You're welcome. Recursion can be tricky, but it's perfect for situations like this :-)
I have tried to implement a solution that incorporates this, but it seems that this function is not updating the value of the original object. Any thoughts?
@KennyThompson: It seems to work for me. jsfiddle.net/cYaML/1 Object references in JavaScript are weird. Maybe you're dealing with a copy and the the original original object?
After some digging, if appears that we are just altering the local variable obj and not the "object" variable (.. bad naming of the example i know.)
|
0

You can define your own Object methods; also I'm using underscore for brevity:

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;
};

Sample usage:

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}}

Comments

0

You could try using Immutable.js, like so:

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

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

newImmutableJsObject.toJS();

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.