12

I have a nested Javascript object like

var data = { 'name':    { 'heading': 'Name', 'required': 1, 'type': 'String' },
             'profile': {
                  'age':   { 'heading': 'Age', 'required': 0, 'type': 'Number' },
                  'phone': { 'heading': 'Phone', 'required': 0, 'type': 'String'},
                  'city':  { 'heading': 'City', 'required': 0, 'type': 'String'},
                  },
             'status':  { 'heading': 'Status', 'required': 1, 'type': 'String' }
           };

Here, I can access the fields as data.profile.age.type or data.name.type. No Issues And if I have dynamic variable names, I can access as below. Again, No Problems.

f = 'profile'; data[f].age.type

But, here I have variable names like 'name', 'profile.age', 'profile.city' etc and obviously I cannot access them as f = 'profile.age'; data[f].type which will not work.

Can anyone guide me how to access them (get/set) in the most straight-forward and simple way?

Note: I tried this and it works for get.

data.get = function(p) { o = this; return eval('o.'+p); };
f = 'profile.age'; data.get(f).name;

though set does not seem to be simple enough. Please let me know, if there are better solutions for get and set as well.

3
  • 2
    You were right to ask this question on SO. Anytime you find yourself using eval in Javascript, you are almost certainly doing the wrong thing. Commented Dec 13, 2010 at 17:40
  • Thanks for letting me know about eval. May be eval is evil! :-) Commented Dec 13, 2010 at 17:53
  • You said it. Take a look at the last suggestion offered here: javascript.crockford.com/code.html Commented Dec 13, 2010 at 18:26

5 Answers 5

8

Don't use eval unless absolutely necessary. :) At least in this case, there are better ways to do it -- you can split the nested name into individual parts and iterate over them:

data.get = function(p) {
  var obj = this;

  p = p.split('.');
  for (var i = 0, len = p.length; i < len - 1; i++)
    obj = obj[p[i]];

  return obj[p[len - 1]];
};

data.set = function(p, value) {
  var obj = this;

  p = p.split('.');
  for (var i = 0, len = p.length; i < len - 1; i++)
    obj = obj[p[i]];

  obj[p[len - 1]] = value;
};
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. Very fast response and helpful.
8

You can just nest the brackets:

var a = 'name', b = 'heading';
data[a][b]; // = `Name`

1 Comment

@vsync: Sure it does. I'm saying that rather than var a='name.heading'; data[a], you can use successive sets of brackets to access deeper levels of the object. So if you know you're looking for something in the profile object, var a='profile',b='age'; data[a][b] works. Obviously, if you need to handle an arbitrary string, the other answers show how to do that. This is an alternative if someone doesn't need the complexity of parsing arbitrary "a.b.c.d" strings.
4

Perhaps a function that takes in the path to the property you're interested in and breaks it up into tokens representing properties. Something like this (this is very rough, of course):

data.get = function(path) {
  var tokens = path.split('.'), val = this[tokens[0]];
  if (tokens.length < 2) return val;
  for(var i = 1; i < tokens.length; i++) {
     val = val[tokens[i]];
  }
  return val;
}

example:

   var f = 'one.two';
   var data = { one: {two:'hello'}};
   data.get = /* same as above */;

   var val = data.get(f);

Comments

1

A clean way to access/set nested values is using reduce in ES6:

const x = ['a', 'b', 'c'], o = {a: {b: {c: 'tigerking'}}}

// Get value: "tigerking"
console.log(x.reduce((a, b) => a[b], o)) 

// Set value: 
x.slice(0, x.length-1).reduce((a, b) => a[b], o)[x[x.length-1]] = 'blossom'

console.log(o) // {a: {b: {c: 'blossom'}}}

So, you can first convert your variable 'profile.age' to an array using 'profile.age'.split('.'), then use the approach above.

Comments

0

This uses the jquery.each() function to traverse down a json tree using a string variable that may or may not contain one or more "."'s. You could alternatively pass in an array and omit the .split();

pathString = something like "person.name"

jsonObj = something like {"person" : {"name":"valerie"}}.

function getGrandchild(jsonObj, pathString){
    var pathArray = pathString.split(".");
    var grandchild = jsonObj;
    $.each(pathArray, function(i, item){
        grandchild = grandchild[item];
    });
    return grandchild;
};

returns "valerie"

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.