30

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?

3
  • Whats wrong with data.address.streetName ? Commented Feb 27, 2012 at 10:14
  • I am getting address.streetName as a variable from somewhere. I mean someone is passing me x where x = "address.streetName" Commented Feb 27, 2012 at 10:32
  • 1
    Hmm, in that case, you'd have to use eval, which is not exactly ideal! To use eval: var your_variable = eval("data." + x); Commented Feb 27, 2012 at 11:19

8 Answers 8

48

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)); 
Sign up to request clarification or add additional context in comments.

6 Comments

+1 I think you have got data.address.streetName right, that is what he is looking for probably though his question isn't clear.
Hmm I will explain it again: address.streetName is a variable coming to me. I have data in json format with me. The situation is like I have data in JSON format and someone is passing "address.streetName" to me and the problem is how should I access value for this key from data
Yes I thinks its the most efficient solution of this problem. Thanks.
Be sure to mark the answer that helped you out as the 'right answer'.
Line 5 should be obj = obj[prop[i]]. Also remember to try-catch errors if property string cannot be found in object. Otherwise an excellent answer. +1
|
24

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.

2 Comments

lodash its pretty straight forward to do this.
@Brian Park your answer made my day man !. Nice stuff. Thanks.
15

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" 

Comments

2

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.

1 Comment

yes correct so is there any efficient way to access nested data compare to following : col = "address.streetName" //key exp = "x" // data; col = col.split(".") for(var i=0; i<col.length; i++) exp+='["' + col[i] + '"]'; eval(exp)
2

you can access it this way data.address.streetName

2 Comments

Yes but I am getting key in string format ...I mean someone is passing me "address.streetName"
can't you just loop through your records and do a if address.streetname == x
2

I did it like this:

var data = { "id": 1, "name": "abc", "addresses": [{ "streetName": "cde", "streetId": 2 }, { "streetName": "xyz", "streetId": 102 }, ] } data2 = data["addresses"] for (let i in data2) { console.log(data2[i]["streetName"]); } 

Comments

1

JavaScript:

function getProperty(json, path) { var tokens = path.split("."); var obj = json; for (var i = 0; i < tokens.length; i++) { obj = obj[tokens[i]]; } return obj; } var data = { id: 1, name: "abc", address: { streetName: "cde", streetId: 2 } }; var fields = ["id", "name", "address.streetName"]; for (var i = 0; i < fields.length; i++) { var value = getProperty(data, fields[i]); console.log(fields[i] + "=" + value); } 

Output:

id=1 name=abc address.streetName=cde 

2 Comments

Thanks Michael ..this is what I am doing..just wondering if there could be more efficient way of doing that..
Just realized I was doing unnecessary eval after constructing data["address"]["streetName"] using for loop. I think your's answer is most efficient. Thanks a lot.
1

This is a function I use to find data in nested objects:

Object.prototype.find = function() { try { return Array.prototype.slice.call(arguments).reduce(function(acc, key) { return acc[key] }, this) } catch(e) { return } } 

Data structure:

data = { "id":1, "name":"abc", "address": { "streetName":"cde", "streetId":2 } } 

Function call:

data.find("address","streetName") 

Returns:

"cde" 

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.