Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript: Access nested values in JSON data using dynamic variable names

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.

like image 520
rsmoorthy Avatar asked Dec 13 '10 17:12

rsmoorthy


2 Answers

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);
like image 161
moribvndvs Avatar answered Nov 03 '22 19:11

moribvndvs


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.

like image 31
Nic Scozzaro Avatar answered Nov 03 '22 19:11

Nic Scozzaro