getPathValue() function for deep objects with arra

2019-02-27 07:11发布

For background, please refer to this question: Access deep object member of embeded JSON

The solutions offered there worked very well with the packed JSON contained in key values.

However, they don't handle the situation where JSON has arrays.

The original function I referenced in the other question DID handle arrays, but it would not handle the packed JSON.

This is the original function:

function getPathValue(obj, path) {
    return new Function('_', 'return _.' + path)(obj);
}

and this is the answer from the first question:

function getValue(object, path) {
    return path
        .split('.')
        .reduce((o, k) => (typeof o === 'string' ? JSON.parse(o) : o)[k], 
object);
}

Again, both work well, but neither offers the whole package.

I need a solution that will do both and it must work in IE11's ES5.

Here is a sample API returned JSON string:

{"id":"0001","type":"donut","name":"Cake","ppu":0.55,"batters":{"batter":[{"id":"1001","type":"Regular"},{"id":"1002","type":"Chocolate"}]},"data":"{\"domain\":\"cooking.com\",\"id\":53819390}"}

I'd like to be able to query values with a path string, for example:

value = getPathValue(obj, 'batters.batter[2].id');

or

value = getPathValue(obj, 'type');

or

value = getPathValue(obj, 'data.domain');

2条回答
可以哭但决不认输i
2楼-- · 2019-02-27 08:05

The following would do the job using a Regex on each value :

const data = {
    "id": "0001",
    "type": "donut",
    "name": "Cake",
    "ppu": 0.55,
    "batters": {
        "batter": [
            {
                "id": "1001",
                "type": "Regular"
            },
            {
                "id": "1002",
                "type": "Chocolate"
            }
        ]
    },
    "data": "{\"domain\":\"cooking.com\",\"id\":53819390}"
}

function getValue(object, path) {
    return path
        .split('.')
        .reduce(function (o, k) {
            const indexSearch = (new RegExp(/\[([0-9]*)\]/)).exec(k)
            const index = indexSearch ? indexSearch[1] : null
            k = k.replace(/\[[0-9]*\]/, '')
            const sub = (typeof o === 'string' ? JSON.parse(o) : o)[k]
            return index ? sub[index] : sub;
        }, object);
}

console.log(getValue(data, 'batters.batter[1]'))
console.log(getValue(data, 'data.domain'))
console.log(getValue(data, 'batters.batter[1].id'))

查看更多
何必那么认真
3楼-- · 2019-02-27 08:07

You could replace the brackets and take the remaining values as keys. Inside of the reducing, you could use a default object for not given objects.

function getValue(object, path) {
    return path
        .replace(/\[/g, '.')
        .replace(/\]/g, '')
        .split('.')
        .reduce(function (o, k) {
            return (typeof o === 'string' ? JSON.parse(o) : (o || {}))[k];
        }, object);
}
var object = {"id":"0001","type":"donut","name":"Cake","ppu":0.55,"batters":{"batter":[{"id":"1001","type":"Regular"},{"id":"1002","type":"Chocolate"}]},"data":"{\"domain\":\"cooking.com\",\"id\":53819390}"},
    path = 'batters.batter[1].id';

console.log(getValue(object, path));

查看更多
登录 后发表回答