Следующая функция отлично справляется с получением значения ключа глубокого объекта с помощью строки с точечной записью:
function getPathValue(obj, path) {
return new Function('_', 'return _.' + path)(obj);
}
Например, он возвращает значение для такого ключа, как «bar», используя в качестве аргумента пути следующее:
'data.abc.foo.bar'
Однако некоторые API-интерфейсы содержат дополнительный строковый JSON в некоторые ключевые значения.
Я ищу усовершенствование вышеупомянутой функции, которое будет обрабатывать этот случай.
Например, собственный сервис WebSocket от Stack:
wss://qa.sockets.stackexchange.com/
возвращает такие строки:
{"action":"155-questions-active","data":"{\"siteBaseHostAddress\":\"stackoverflow.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\":\"https://stackoverflow.com/questions/53819390/should-i-start-with-webgl1-or-webgl2-when-using-three-js\",\"ownerUrl\":\"https://stackoverflow.com/users/8226111/romanrogers\",\"ownerDisplayName\":\"romanrogers\",\"apiSiteParameter\":\"stackoverflow\"}"}
И я хотел бы иметь возможность использовать указанную выше функцию для получения значений с помощью входной строки, например:
'data.bodySummary'
Возможно, входная строка могла бы выглядеть примерно так:
'data/bodySummary'
где солидус (/ косая черта) представляет JSON.parse ().
Обратите внимание: это должно быть динамическим, поскольку я бы хотел, чтобы конечный пользователь мог выбирать произвольные ключи для возврата значений в общем случае.
Вы можете проверить, является ли элемент, из которого вы берете свойство, строкой, и выполнить синтаксический анализ. Возвращает значение свойства.
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\":\"stackoverflow.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\":\"https://stackoverflow.com/questions/53819390/should-i-start-with-webgl1-or-webgl2-when-using-three-js\",\"ownerUrl\":\"https://stackoverflow.com/users/8226111/romanrogers\",\"ownerDisplayName\":\"romanrogers\",\"apiSiteParameter\":\"stackoverflow\"}"};
console.info(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\":\"stackoverflow.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\":\"https://stackoverflow.com/questions/53819390/should-i-start-with-webgl1-or-webgl2-when-using-three-js\",\"ownerUrl\":\"https://stackoverflow.com/users/8226111/romanrogers\",\"ownerDisplayName\":\"romanrogers\",\"apiSiteParameter\":\"stackoverflow\"}"};
console.info(getValue(data, 'data.bodySummary'));
Мне это очень нравится. Но мое требование - IE11 и ES5. Можете ли вы переделать это без функции стрелки?
Спасибо. Прекрасно работает.
Есть ли способ улучшить это, чтобы оно работало, когда в JSON есть массивы, а путь включает один или несколько? Дайте мне знать, и я могу начать новый вопрос, если хотите.
Было бы лучше задать новый вопрос с примером данных, которые у вас есть, и более подробным обзором, что вы хотите, поскольку это можно обсудить в разделе комментариев.
Я только что разместил новый вопрос: stackoverflow.com/q/53841772/3566998
Вот функция, которая принимает объект или строку JSON в качестве первого параметра, строку пути ключа или массив в качестве второго параметра и рекурсивно просматривает объект с помощью пути ключа.
let object = {"action":"155-questions-active","data":"{\"siteBaseHostAddress\":\"stackoverflow.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\":\"https://stackoverflow.com/questions/53819390/should-i-start-with-webgl1-or-webgl2-when-using-three-js\",\"ownerUrl\":\"https://stackoverflow.com/users/8226111/romanrogers\",\"ownerDisplayName\":\"romanrogers\",\"apiSiteParameter\":\"stackoverflow\"}"};
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.info(valueAtKeyPath(object, 'action'))
console.info(valueAtKeyPath(object, 'data.id'))
Хорошо, но он не возвращает строковые значения для таких путей, как: valueAtKeyPath (object, 'action')
@ExcelHero - я понимаю, о чем вы. Фиксированный.
Спасибо тебе за это. Оно работает. Я также ценю то, что вы обновили его. Я выбираю Nina's, потому что это было первое, и мне нравится, насколько оно лаконично. Мне также нравится, что он возвращает строку вместо объекта для пути: 'данные'
Сегодня проголосовали против ... почему?