访问嵌入式的深层对象成员JSON

Access deep object member of embeded JSON

以下函数在检索带有点标记的字符串的深度对象键值方面做得非常出色:

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

例如,它 return 是像 "bar" 这样的键的值,使用以下作为路径参数:

'data.abc.foo.bar'

但是,一些 API 将额外的字符串化 JSON 打包到一些键值中。

我正在寻找可以处理这种情况的上述功能的增强功能。

比如Stack自带的WebSocket服务:

wss://qa.sockets.stackexchange.com/

returns 这样的字符串:

{"action":"155-questions-active","data":"{\"siteBaseHostAddress\":\"whosebug.com\",\"id\":53819390,\"titleEncodedFancy\":\"Should I start with webGL1 or webGL2 when using Three.js\",\"bodySummary\":\"Spent some time learning and understanding the basics of webGL and I'm now diving into Three.js.\n\nI noticed that I have the option of using webGL1 or webGL2. Seems as if webGL1 is the default, however ...\",\"tags\":[\"three.js\",\"webgl\"],\"lastActivityDate\":1545064508,\"url\":\"",\"ownerUrl\":\"https://whosebug.com/users/8226111/romanrogers\",\"ownerDisplayName\":\"romanrogers\",\"apiSiteParameter\":\"Whosebug\"}"}

而且我希望能够使用上述函数通过输入字符串检索值,例如:

'data.bodySummary'

也许输入字符串类似于:

'data/bodySummary'

其中斜线(/斜杠)表示 JSON.parse()。

注意,这需要是动态的,因为我想让最终用户在一般情况下可以 select 任意键到 return 值。

您可以检查您从中获取 属性 的项目是否是字符串并执行解析。 return的值为属性.

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

var data = {"action":"155-questions-active","data":"{\"siteBaseHostAddress\":\"whosebug.com\",\"id\":53819390,\"titleEncodedFancy\":\"Should I start with webGL1 or webGL2 when using Three.js\",\"bodySummary\":\"Spent some time learning and understanding the basics of webGL and I'm now diving into Three.js.\n\nI noticed that I have the option of using webGL1 or webGL2. Seems as if webGL1 is the default, however ...\",\"tags\":[\"three.js\",\"webgl\"],\"lastActivityDate\":1545064508,\"url\":\"",\"ownerUrl\":\"https://whosebug.com/users/8226111/romanrogers\",\"ownerDisplayName\":\"romanrogers\",\"apiSiteParameter\":\"Whosebug\"}"};

console.log(getValue(data, 'data.bodySummary'));

ES5

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

var data = {"action":"155-questions-active","data":"{\"siteBaseHostAddress\":\"whosebug.com\",\"id\":53819390,\"titleEncodedFancy\":\"Should I start with webGL1 or webGL2 when using Three.js\",\"bodySummary\":\"Spent some time learning and understanding the basics of webGL and I'm now diving into Three.js.\n\nI noticed that I have the option of using webGL1 or webGL2. Seems as if webGL1 is the default, however ...\",\"tags\":[\"three.js\",\"webgl\"],\"lastActivityDate\":1545064508,\"url\":\"",\"ownerUrl\":\"https://whosebug.com/users/8226111/romanrogers\",\"ownerDisplayName\":\"romanrogers\",\"apiSiteParameter\":\"Whosebug\"}"};

console.log(getValue(data, 'data.bodySummary'));

这是一个函数,它将对象或 JSON 字符串作为第一个参数,将关键路径字符串或数组作为第二个参数,并使用关键路径递归遍历对象。

let object = {"action":"155-questions-active","data":"{\"siteBaseHostAddress\":\"whosebug.com\",\"id\":53819390,\"titleEncodedFancy\":\"Should I start with webGL1 or webGL2 when using Three.js\",\"bodySummary\":\"Spent some time learning and understanding the basics of webGL and I'm now diving into Three.js.\n\nI noticed that I have the option of using webGL1 or webGL2. Seems as if webGL1 is the default, however ...\",\"tags\":[\"three.js\",\"webgl\"],\"lastActivityDate\":1545064508,\"url\":\"",\"ownerUrl\":\"https://whosebug.com/users/8226111/romanrogers\",\"ownerDisplayName\":\"romanrogers\",\"apiSiteParameter\":\"Whosebug\"}"};

function asObject(str) {
    try {
        return JSON.parse(str);
    } catch (e) {
        return str;
    }
}


function valueAtKeyPath(o, path) {
    o = asObject(o);
    if (typeof path === 'string') path = path.split('.');
    
    if (!o || !path.length) return o;
    return valueAtKeyPath(o[path[0]], path.slice(1));
}

console.log(valueAtKeyPath(object, 'action'))
console.log(valueAtKeyPath(object, 'data.id'))