0

Have a situation where I'm being provided a path from an external source, and I need to pull that key out of an object and return the value.

The document schema is also unknown at design time, so this has to be fully flexible.

eval() does what I want, but I'm doing my due diligence to see if there's another way.

var obj = {"a": {"b": {"c": 42}, "d": [8,9]}}
var path = 'a.b.c';
eval('obj.' + path);
42

Anyone know a way, without 'eval', that I can use the string 'a.b.c' to find that nested value in obj?

This must support indexes into lists as well:

var path = 'a.d[1]';
eval('obj.' + path);
9

I can use jQuery if it offers a viable solution, I just don't see anything evident.

Thanks!

hikaru
  • 2,444
  • 4
  • 22
  • 29
  • 1
    Well yeah, it's easy(ish). Parse the path, then access the properties using bracket notation. – Kevin B May 01 '14 at 15:04
  • @JonathanLonowski: I like the `Object.byString` function from that question :-) – gen_Eric May 01 '14 at 15:23
  • Thanks everyone! Don't know how I missed the other similar question, but one of the answers there, plus @RocketHazmat's answer below got me what I needed. – hikaru May 01 '14 at 16:00

1 Answers1

2

Recursion is the solution here.

function getVal(path, obj){
    if(path.length === 1){
        return obj[path[0]];
    }
    else{
        return getVal(path, obj[path.shift()]);
    }
}

var obj = {"a": {"b": {"c": 42}, "d": [8,9]}};
var path = 'a.b.c';

var val = getVal(path.split('.'), obj);
console.log(val);

This will give you 42. It doesn't work with 'a.d[1]' yet, but it can be added in.

UPDATE: Here's an updated version that works with 'a.d[1]'.:

function getVal(path, obj){
    // Get the next "key" in the stack
    var key = path.shift();

    // Check for bracket notation
    if(key.indexOf('[') > -1){
        var match = key.match(/(\w+)\[(\d+)\]/);
        if(match !== null){
            // Get the "next" key
            key = match[2];
            obj = obj[match[1]];
        }
    }

    // Return the value if done, otherwise, keep going
    return path.length === 0 ? obj[key] : getVal(path, obj[key]);
}

var obj = {"a": {"b": {"c": 42}, "d": [8,9]}};
var path = 'a.d[1]';

var val = getVal(path.split('.'), obj);
console.log(val);
gen_Eric
  • 223,194
  • 41
  • 299
  • 337