Reputation: 113
Say I have a json
jsonData = {
"id":"dfd",
"properties":{
"Pri":"2",
"Brief Description":"asdf",
"Description":"",
"tree":{
"var": "2",
"rav": "3"
}
}
}
and a list
var variableArray = ['properties', 'tree', 'var'];
If I want to access the value of var and edit it. How would I do that while maintaining the value of jsonData?
I've tried
for (var i = 0; i < variableArray.length; i++) {
jsonData = jsonData[variableArray[i]];
}
jsonData = 'new value';
But I can no longer access the whole jsonData.
What are some way to implement this?
Upvotes: 0
Views: 66
Reputation: 1075209
JavaScript doesn't have references to properties, which is effectively what you're trying to use there.
Instead, you can give yourself a method that will traverse an object and either retrieve or assign a property in it. Here's a quick and dirty in ES5 and earlier:
function accessPath(obj, path, value) {
var o = obj;
var i = 0;
var last = path.length - 1;
while (i < last) {
o = o[path[i]];
++i;
}
if (arguments.length < 3) {
// Getting
return o[path[last]];
} else {
// Setting
return o[path[last]] = value;
}
}
Live example:
function accessPath(obj, path, value) {
var o = obj;
var i = 0;
var last = path.length - 1;
while (i < last) {
o = o[path[i]];
++i;
}
if (arguments.length < 3) {
// Getting
return o[path[last]];
} else {
// Setting
return o[path[last]] = value;
}
}
var data = {
"id":"dfd",
"properties":{
"Pri":"2",
"Brief Description":"asdf",
"Description":"",
"tree":{
"var": "2",
"rav": "3"
}
}
}
var path = ['properties', 'tree', 'var'];
console.log("Existing: " + accessPath(data, path));
accessPath(data, path, "new value");
console.log("Updated: " + accessPath(data, path));
console.log("Confirm: " + data.properties.tree.var);
Looks fairly similar in ES2015+, other than perhaps how you check if value
is supplied.
Not pretty, but fairly efficient.
Actually, we can go further if we return an object with a getter and setter, which would look a bit like a property reference even though it isn't actually:
function makeAccessor(obj, path) {
var o = obj;
var i = 0;
var last = path.length - 1;
var lastName = path[last];
while (i < last) {
o = o[path[i]];
++i;
}
return {
get value() {
return o[lastName];
},
set value(value) {
o[lastName] = value;
}
};
}
Then, getting the accessor:
var accessor = makeAccessor(data, path);
And using it:
console.log(accessor.value);
accessor.value = "new value";
function makeAccessor(obj, path) {
var o = obj;
var i = 0;
var last = path.length - 1;
var lastName = path[last];
while (i < last) {
o = o[path[i]];
++i;
}
return {
get value() {
return o[lastName];
},
set value(value) {
o[lastName] = value;
}
};
}
var data = {
"id":"dfd",
"properties":{
"Pri":"2",
"Brief Description":"asdf",
"Description":"",
"tree":{
"var": "2",
"rav": "3"
}
}
}
var path = ['properties', 'tree', 'var'];
var accessor = makeAccessor(data, path);
console.log("Existing: " + accessor.value);
accessor.value = "new value";
console.log("Updated: " + accessor.value);
console.log("Confirm: " + data.properties.tree.var);
Upvotes: 2
Reputation: 135397
You could write little helpers read
and write
that do what you need – note data
is not altered by use of read
const read = (o, [k,...ks]) =>
o ? k === undefined ? o
: read (o[k], ks)
: undefined
const write = (o, [k,...ks], v) =>
o ? ks.length === 0 ? (o[k] = v, null)
: write (o[k], ks, v)
: undefined
const data = {
"id":"dfd",
"properties":{
"Pri":"2",
"Brief Description":"asdf",
"Description":"",
"tree":{
"var": "2",
"rav": "3"
}
}
}
// read
console.log (read (data, ['properties', 'tree', 'var']))
// => 2
console.log (read (data, ['foo', 'bar', 'barf']))
// => undefined (signals failure)
// write
console.log (write (data, ['properties', 'tree', 'var'], 'new value'))
// => null (signals success)
console.log (write (data, ['foo', 'bar', 'barf'], 'new value'))
// => undefined (signals failure)
// read updated value
console.log (read (data, ['properties', 'tree', 'var']))
// => "new value"
By the way, to add to others' comments, JavaScript Object Notation is what JSON stands for. It's the Notation part that makes JSON different from "JSO" (JavaScript Object). More simply put, JSON is a string representation of a JavaScript Object. You'll know it's not JSON if it's not a string.
Upvotes: 0