4

I have an input array, with path like

var path = ["foo","bar","baz"];

And I have an object

var obj = {
    "foo": {
         "bar": {
              "baz": "cake"
         },
         "notbar": {
              "another": "value"
         }
    }
}

And i want to change the "baz" value from the path. I know i can use

obj[path[0]][path[1]][path[2]] = "value";

but i dont know how long the array will be. both php and javascript anwsers are appreciated!

  • 1
    Once json decoded this could help: http://stackoverflow.com/questions/27929875/how-to-write-getter-setter-to-access-multi-leveled-array-by-dot-separated-key-na not sure how to implement in JS. – AbraCadaver Feb 23 '15 at 20:09
  • It's ok, php anwser is appreciated as well! thanks –  Feb 23 '15 at 20:23

3 Answers3

3

Try this:

function getValueByPath(obj, path) {
    var result = obj,
        i;
    for (i = 0; i < path.length; i++) {
        try {
            result = result[path[i]];
        }
        catch (e) {
            return undefined;
        }
    }
    return result
}

function setValueByPath(obj, path, value) {
    var result = obj,
        i;
    for (i = 0; i < path.length - 1; i++) {
        try {
            result = result[path[i]];
        }
        catch (e) {
            return;
        }
    }

    if (typeof value == 'object') {
        result[path[i]] = value;
    }
}

Given your variable initializations, getValueByPath(obj, path) returns 'cake', then set it as setValueByPath(obj, path, 'value'); now getValueByPath(obj, path) returns 'value'.

0

Something like this should work

function modify(obj, path, val) {
    var e = obj, l = path.pop();

    path.forEach(function(x) { x in e ? e = e[x] : e; });

    if (typeof val === 'undefined') return e[l];
    e[l] = val;
    return e;
}

You could call it as getter or a setter

var what = modify(obj, path);  // returns "cake"

modify(obj, path, 'new value');

var what2 = modify(obj, path);  // now return "new value", object was modified

FIDDLE

adeneo
  • 312,895
  • 29
  • 395
  • 388
-1

Here goes my not pretty but working solution:

function setPropertyByPath(obj, path, value) {
    if(!path || path.length === 0) return;

    var property = path[0];
    for(var i = 1; i < path.length; i++) {
      property += "." + path[i];
    }
    property = "obj." + property + " = \"" + value + "\"";
    eval(property)
}

Then you call

setPropertyByPath(obj, path, "newValue");

Here is a working FIDDLE

nanndoj
  • 6,580
  • 7
  • 30
  • 42
  • that's actually quite smart using eval to transform string "." to object values! –  Feb 23 '15 at 20:38