简体   繁体   中英

json nested lookup using string based key in javascript

With a javascript json object like this:

var data = {
    blog : {
        title: "my blog",
        logo: "blah.jpg",
    },
    posts : [
        {
            title: "test post",
            content: "<p>testing posts</p><br><p>some html</p>"
        },
    ]
}

var lookup = "blog.title" //this gets generated from a template file

Now I know you can do something like, but these don't quite do what I need:

console.log(data['blog']);    //works
console.log(data.blog.title); //works
console.log(data['blog']['title']); //works, but i dont know the depth of the lookup

But I need to be able to do something like the code below because I can't hardcode the structure, it gets generated and stored in lookup each time. Do I have to build this functionality using string cutting and recursion?? I really hope not

console.log(data['blog.title']); //does not work
console.log(data[lookup]);       //does not work

EDIT....

Okay, possibly found a workaround. I don't know if this is safe or recommended practice, so comments on that would be great. Or alternative methods. So combining this with the code above.

var evaltest = "var asdf ="+JSON.stringify(data)+";\n"
evaltest += "asdf."+lookup
console.log(eval(evaltest)) //returns correctly "my blog" as expected

You could use dottie https://www.npmjs.org/package/dottie , which allows you to deep traverse an object using strings

var values = {
    some: {
        nested: {
            key: 'foobar';
        }
    }
}

dottie.get(values, 'some.nested.key'); // returns 'foobar'
dottie.get(values, 'some.undefined.key'); // returns undefined

您可以使用:

data['blog']['title']

I've experimented with a couple ways of doing this including eval and using a dictionary lookup with switch(exp.length). This is the final version (comments stripped) I created:

var deepRead = function (data, expression) {

    var exp = expression.split('.'), retVal;

    do {
        retVal = (retVal || data)[exp.shift()] || false;
    } while (retVal !== false && exp.length);

    return retVal || false;

};

//example usage 
data = {
    a1: { b1: "hello" },
    a2: { b2: { c2: "world" } }
}

deepRead(data, "a1.b1") => "hello"
deepRead(data, "a2.b2.c2") => "world"
deepRead(data, "a1.b2") => false
deepRead(data, "a1.b2.c2.any.random.number.of.non-existant.properties") => false

Here's the Gist with full commenting: gist.github.com/jeff-mccoy/9700352 . I use this to loop over several thousand items and have had no issues with deep-nested data. Also, I'm not wrapping in try/catch anymore due to the (small) performance hit: jsPerf .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM