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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.