How to access nested JSON data
Let say I have json data like
data = {"id":1,
"name":"abc",
"address": {"streetName":"cde",
"streetId":2
}
}
Now I am getting fields to be accessed from this json data like : fields = ["id", "name", "address.streetName"]
How could I access third field (address.streetName
) from given json data in most efficient way?
data.fields[2]
doesn't work
One possibility is I construct data[address][streetName]
string using a for loop and do eval of that but is there any efficient way of doing this?
To be honest, I can't understand your problem. JSON is already structured out, why do you need to change the structure?
In you case, I would access it as follows:
data.address.streetName;
If, by any chance, what you want is to traverse the data, you would need:
function traverse_it(obj){
for(var prop in obj){
if(typeof obj[prop]=='object'){
// object
traverse_it(obj[prop[i]]);
}else{
// something else
alert('The value of '+prop+' is '+obj[prop]+'.');
}
}
}
traverse_it(data);
Update
After reading below, what this user needs seems more obvious. Given property names as a string, s/he wants to access the object.
function findProp(obj, prop, defval){
if (typeof defval == 'undefined') defval = null;
prop = prop.split('.');
for (var i = 0; i < prop.length; i++) {
if(typeof obj[prop[i]] == 'undefined')
return defval;
obj = obj[prop[i]];
}
return obj;
}
var data = {"id":1,"name":"abc","address":{"streetName":"cde","streetId":2}};
var props = 'address.streetName';
alert('The value of ' + props + ' is ' + findProp(data, props));
If you use lodash(a very popular utility library), you can use _.get()
.
e.g.
var data = {
"id":1,
"name": "abc",
"address": {
"streetName": "cde",
"streetId":2
}
}
_.get(data, 'address.streetName');
// 'cde'
_.get(data, ['address', 'streetName']);
// 'cde'
If it involves an array, you can use string path like 'address[0].streetName'
as well.
e.g.
var data = {
"id":1,
"name": "abc",
"addresses": [
{
"streetName": "cde",
"streetId": 2
},
{
"streetName": "xyz",
"streetId": 102
},
]
}
_.get(data, 'addresses[0].streetName');
// cde
_.get(data, [address, 1, streetName]);
// xyz
Internally, it uses toPath()
function to convert string path (e.g. address.streetName
) into an array (e.g. ['address', 'streetName']
), and then uses a function to access the data at the given path within the object.
Other similar utility functions include _.set()
and _.has()
. Check them out.
Long story short, you can use the array notation object[property]
instead of object.property
; this is specially useful when the keys contains special characters:
var data = {
"id": 1,
"name": "abc",
"address": {
"streetName": "cde",
"streetId": 2
}
}
data.address.streetName; // (1) dot notation
data["address"]["streetName"]; // (2) array notation
var field = "streetName";
data["address"][field]; // (3) variable inside array notation
var fields = "address.streetName".split(".");
data[fields[0]][fields[1]]; // (4) specific to your question
You can use the typeof
operator to check whether a property exists or not before using it:
typeof data["address"]["streetName"]; // returns "string"
typeof data["address"]["foobarblah"]; // returns "undefined"
Your data
variable doesn't have a fields
property, and that's why data.fields[2]
doesn't work. I think what you're trying to do there is data[fields[2]]
, which would work for a simple object, but you can't index into a complex object like that.