Im trying to figure out if its possible to update a JavaScript object, using a string as the path.
In the example below, I'm trying to figure out how I can update the first books price using
store>book>0>price
as my path.
I know I can access this by writing data['store']['book'][0]['price']
but I need to be able to do this dynamically. Ive tried a few things but had no luck. Any Ideas?
This needs to work for any depth , not a fixed depth
Data:
var data = {
"store": {
"book": [
{ "category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{ "category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
}
}
var path = "store>book>0>price"
Function:
function updateObject(object, path, data) {
var pathArray = path.split(">");
// Some code here
}
updateObject(data, path, "10.00");
Update
As felix pointed out the answer can be found here. Dynamic deep setting for a JavaScript object
Here is a working example for my scenario http://jsfiddle.net/blowsie/Sq8j3/9/
function updateObject(object, newValue, path){
var stack = path.split('>');
while(stack.length>1){
object = object[stack.shift()];
}
object[stack.shift()] = newValue;
}
You want to update your method signature to accept the: object you're modifying, the path string, and the value you're assigning to the final path property.
function updateObject(data, path, value) {
var pathArray = path.split(">");
var pointer = data; // points to the current nested object
for (var i = 0, len = pathArray.length; i < len; i++) {
var path = pathArray[i];
if (pointer.hasOwnProperty(path)) {
if (i === len - 1) { // terminating condition
pointer[path] = value;
} else {
pointer = pointer[path];
}
} else {
// throw error or terminate. The path is incorrect
}
}
}
Or recurse. Or use a while loop. But this is the general idea.
Fiddle: http://jsfiddle.net/Sq8j3/8/
It's slightly confusing that you've called your object data
but that data
is also an argument of your function. I've changed the argument's name therefore to newVal
in order to clear up this potential problem.
This loops through the path and constantly resets a variable called e
which starts by pointing to the data
object generally and gets more specific as we loop. At the end, you should have an almost reference to the exact property -- we use the last part of the path to set the new value.
function updateObject(newVal, path) {
var pathArray = path.split(">"),
i = 0,
p = pathArray.length - 1, // one short of the full path
e = data; // "import" object for changing (i.e., create local ref to it)
for (i; i < p; i += 1) { // loop through path
if (e.hasOwnProperty(pathArray[i])) { // check property exists
e = e[pathArray[i]]; // update e reference point
}
}
e[pathArray[i]] = newVal; // change the property at the location specified by path to the new value
};
You might need to add something to catch errors. I have put a check in with the hasOwnProperty()
call but you might need something more elaborate than this.
UPDATE
Had made a silly mistake in the code before but it should be working now. As evidenced here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With