-2

I have JSON that looks like this:

 {
    "greeting": {
        "hello": ["world", "josue", "everybody"]
    }
 }

I am wondering why I cannot use a string to access it's properties like so:

var str = 'greeting.hello';
var obj = { "greeting": { "hello": ["world", "josue", "everybody"] } };
console.log(obj.str);

The above code logs undefined.

However, if I use eval() (which I really don't want to...), it works as expected.

var str = 'greeting.hello';
var obj = { "greeting": { "hello": ["world", "josue", "everybody"] } };
console.log(eval('obj.'+str));

That returns ["world", "josue", "everybody"].

Why can't I use the first example? Is there a way to access the hello key using a string like shown in the first example (without using eval or modifying the JSON)?

Josue Espinosa
  • 5,009
  • 16
  • 47
  • 81

3 Answers3

2

In Angular you use the $parse service (ref):

var str = 'greeting.hello';
var obj = { "greeting": { "hello": ["world", "josue", "everybody"] } };
var getter = $parse(str);
var theValue = getter(obj);
Nikos Paraskevopoulos
  • 39,514
  • 12
  • 85
  • 90
1

What you are doing with console.log(obj.str); is trying to access the "str" property of the object(which doesn't exist). To access the property you want use console.log(obj["greeting"]["hello"]); or obj.greeting.hello. This is what your doing when evaling the code as your evaling the string "obj.greeting.hello".

You could write a function like this to do want you want as well.

function navigate(str, obj) { 
    var out = obj;
    str.split(".").forEach(function (el) {
        out = out[el];
    });
    return out;
}
ShaneQful
  • 2,140
  • 1
  • 16
  • 22
  • 1
    obj.str and obj[str] are the same thing. – Josue Espinosa Aug 06 '14 at 20:26
  • Sorry Josue had miss-read the question corrected it 40 secs before you commented but you mustn't have seen the update – ShaneQful Aug 06 '14 at 20:28
  • Thanks for the answer. I comprehend that `obj.greeting.hello` would be the way to go, except I want to do it via string. – Josue Espinosa Aug 06 '14 at 20:32
  • 1
    Can't do it natively in javascript but many frameworks have this ability. You can also write your own which is safer than evaling the code. e.g `function navigate(str, obj) { var out = obj;str.split(".").forEach(function (el) {out = out[el];});return out;}` added code above so it can be indented. – ShaneQful Aug 06 '14 at 20:37
  • @ShaneQful Seems like a waste of time to me(access object property with string), but if you were building or extending a framework it would be handy, since you wouldn't have to map each json interaction manually, instead using the supplied function would be beneficial for more rapid development. – r3wt Aug 06 '14 at 20:40
0

In your first example, accessing obj.str will try to access the str property of obj (literally "str", not the value of the str variable).

If str contains a key name, you can access an object property by using the bracket notation like this: obj[str]. However, this notation doesn't allow to use a property path like you'd like to.

Here is a function that splits the property path and accesses the right property:

function getProperty(obj, str) {
    var path = str.split(".");
    if (path.length == 0) {
        return undefined;
    }
    var pointer = obj;
    for (var i = 0, l = path.length; i< l; i++) {
        pointer = pointer[path[i]];
    }
    return pointer;
}

Now you can access properties with dot-separated paths:

var str = 'greeting.hello';
var obj = { "greeting": { "hello": ["world", "josue", "everybody"] } };
console.log(getProperty(obj, str));