Каковы наилучшие способы ссылки на ветви древовидной структуры JSON?
Итак, у меня есть файл JSON, который анализируется в объект в Javascript. Я знаю, о чем ты думаешь: счастливчик. JSON - это, по сути, блок-схема в виде большого дерева. Вот небольшой пример того, чего я пытаюсь достичь:
tree = {
"options": [
{
"options": [
{
"name": "target",
},
],
},
{
"options": [
{
"link": "...?",
},
],
},
]
}
Так что в этом примере я буду глубоко во второй ветви (где это говорит "link"
) и я хочу иметь возможность перейти к ветви, которая содержит "name": "target"
, Это JSON, помните, поэтому он должен быть строкой (если нет родного для ссылки?! там?), Но я не знаю, как лучше отформатировать это.
На мой взгляд, у меня есть по крайней мере несколько вариантов.
Я мог бы искать. Если
name
был уникальным, я мог масштабировать дерево в поисках элементов, пока не нашел его. Я никогда не делал с Javascript раньше, но я ожидаю, что это будет медленно.Я мог бы использовать путь навигации, как
options:1:options:1
который описывает каждый ключ для пути. Опять же, я никогда не делал этого, но, при условии отсутствия ошибок, это было бы намного быстрее. Как бы вы это реализовали?
Есть ли другие варианты, доступные для меня? Что кажется лучшим? Есть ли способ распаковать это при декодировании JSON, или это рецепт для бесконечного цикла?
1 ответ
Как насчет link: 'tree.options[0].options[0]'
затем eval(path.to.link)
?
Следующие образцы были протестированы только с Chrome. Одно и то же дерево для всех:
var tree = { level1: [{ key: 'value' }] };
нет eval
function resolve(root, link) {
return (new Function('root', 'return root.' + link + ';'))(root);
}
var value = resolve(tree, path.to.link);
Отступление к window
function resolve(root, link) {
return (new Function(
'root', 'return root.' + (link || root) + ';'
))(link ? root : window);
}
resolve(tree, 'level1[0].key'); // "value"
resolve('tree.level1[0].key'); // "value"
Ловля ошибок
Блок try/catch не дает ошибочным ссылкам генерировать ошибки.
function resolve(root, path) {
try {
return (new Function('root', 'return root.' + path + ';'))(root);
} catch (e) {}
}
resolve(tree, 'level1[0].key'); // "value"
resolve(tree, 'level1[1].key'); // undefined
Использование пользовательского формата пути
Хорошая часть здесь в том, что мы можем передать объект или массив как root
, Также обратите внимание, что мы можем заменить косую черту в path.split('/')
с любым символом по нашему выбору.
function resolve(root, path) {
path = '["' + path.split('/').join('"]["') + '"]';
return (new Function('root', 'return root' + path + ';'))(root);
}
resolve(tree.level1, '0/key'); // "value"
resolve(tree, 'level1/0/key'); // "value"
resolve(tree, 'level1/0'); // Object {key: "value"}