【问题标题】:What are the best ways to reference branches of a JSON tree structure?引用 JSON 树结构的分支的最佳方法是什么?
【发布时间】:2013-08-22 13:02:01
【问题描述】:

所以我有一个 JSON 文件,它被解析为 Javascript 中的对象。我知道你在想什么:幸运的家伙。 JSON本质上是一个大树形式的流程图。这是我要实现的目标的一小部分示例:

tree = {
    "options": [
        {
            "options": [
                {
                    "name": "target",
                },
            ],
        },
        {
            "options": [
                {
                    "link": "...?",
                },
            ],
        },
    ]
}

因此,在本例中,我将深入第二个分支(其中显示为"link"),并且我希望能够跳转到包含"name": "target" 的分支。记住这是 JSON,所以它需要是一个字符串(除非有一个用于链接的本机?!有吗?)但我不知道如何最好地格式化它。

在我看来,我至少有几个选择。

  1. 我可以搜索。如果name 是唯一的,我可以缩放树以查找元素,直到找到它。我以前从未使用过 Javascript,但我预计它会很慢。

  2. 我可以使用像options:1:options:1 这样的导航路径来描述路径的每个键。同样,我从来没有这样做过,但是假设没有错误,它会快很多。你将如何实现它?

我还有其他选择吗?什么看起来最好?有没有办法在 JSON 解码时解包,或者这是一个无限循环的秘诀?

【问题讨论】:

  • 不清楚“解析dict对象”是什么意思。
  • 尝试并找到一个新项目。哈哈。你肯定有泡菜。这似乎是您开发自己的功能的案例,该功能将树枝一根一根地撕下然后对它们起作用。它是 JSON,所以我不知道“速度”实际上会成为一个因素。
  • @Pointy 我不知道如何更好地表达它。我想“获取”包含名称/值对"name":"target" 的对象。原谅我,我是一个 Pythonista,谈论 Javascript,所以我肯定会理解一些不正确的术语。

标签: javascript json tree


【解决方案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"}

【讨论】:

  • 这当然很有趣...大大简化了事物的编码方面,安全性在这里并不是真正的问题,因为我控制着整个事物。
  • 没有-eval 的版本绝对应该安抚那些足够在意的人,但除了 eval 的任意安全风险之外,一种方法相对于另一种方法的优势是什么?
  • 我认为你的情况没有。我想说您可以更好地控制路径的来源,例如,您可以将树的副本传递给 resolve : resolve(treeCopy, path.to.link)
  • @downvoter 我猜你对动态代码评估投了反对票。恐惧!恐惧!好吧,只要您保持对输入的控制,这不一定是邪恶的:nczonline.net/blog/2013/06/25/eval-isnt-evil-just-misunderstood.
  • 动态代码评估的替代方法可以在这里找到:stackoverflow.com/q/6491463/1636522
猜你喜欢
  • 2019-06-01
  • 2011-05-15
  • 1970-01-01
  • 1970-01-01
  • 2023-03-03
  • 2016-09-29
  • 1970-01-01
  • 2010-10-05
  • 1970-01-01
相关资源
最近更新 更多