是否有JSON等效于XQuery/XPath?

252

在搜索复杂的JSON数组和哈希表中的项目时,例如:

[
    { "id": 1, "name": "One", "objects": [
        { "id": 1, "name": "Response 1", "objects": [
            // etc.
        }]
    }
]

有没有一种查询语言可以用来在[0].objects中查找id等于3的项?


5
+1 好主意。明天我会写下来… - user142019
2
不是XPath,但我发现JLinq非常好用(可以使代码读起来像in(...).where(...).select(...)):http://hugoware.net/Projects/jLinq。 - pimvdb
4
这很令人沮丧,因为有很多的库存在,但没有一种被广泛接受的标准。我们有一个被第三方使用的库,因此我们需要提供一种广泛知晓和使用的查询语言。 - David Thielen
1
当然,你可以使用jsel - https://github.com/dragonworx/jsel - 假设你有一个包含JSON对象的变量data,你可以编写:jsel(data).select("//*[@id=3]"),它将返回包含id键为3的对象。 - Ali
这里的一切似乎都很过时。我找到的最新和维护良好的解决方案是https://github.com/dfilatov/jspath。 - Andrew Mao
显示剩余6条评论
19个回答

137

没错,它叫做 JSONPath:

它也被整合到了 DOJO 中。


3
Brian的回答表明在dojo中应该使用jsonQuery模块而不是jsonPath模块。 - hugomg
5
这个有多可靠?而且我找不到Java或C#版本,这对我们来说是致命的。 - David Thielen
2
这个链接提供了Javascript和PHP的实现。如果你需要Java的实现,可以在这里找到:http://code.google.com/p/json-path/。 - Matthias Ronge
2
我应该提到,JSONPath不是基于XPath正式语义的。JSONiq可能是一个更好的选择。 - wcandillon
1
@Paramaeleon 这很好。顺便说一下,该项目已经migrated to GitHub。鉴于人们不断评论此事,Mike可能想将此添加到答案中。 - Franklin Yu
显示剩余5条评论

29

JMESPath是一款非常成熟的库,具有详细的规范和支持多种语言的功能。

语法示例:
// Select a single item
people[1].firstName

// Select a slice of an array
people[0:5]

// Select all the first names
people[*].firstName

// Select all first names based on search term
people[?state=='VA'].firstName

// Count how many people are over 35
length(people[?age>`35`])

// Select only the name and age of people over 35
people[?age>`35`].{name: name, age: age}

// Join expressions together to sort and join elements into a string
people[?state == 'WA'].name | sort(@) | join(', ', @)

文档中,您可以尝试更多实时示例。

这个JS库被压缩后有19kb,可能比一些库要大,但考虑到其广泛的功能,您可能会觉得它值得。

其他选项

还有一些其他选项可用于遍历/过滤JSON数据,以及一些语法示例可帮助您进行比较...

  • JSPath
    .automobiles{.maker === "Honda" && .year > 2009}.model

  • json:select()(更像CSS选择器)
    .automobiles .maker:val("Honda") .model

  • JSONPath(更像XPath)
    $.automobiles[?(@.maker='Honda')].model


很棒的总结和示例,也因为提到了在CSS选择器或XPath中发现的灵感。 - Jochem Schulenklopper

24

我认为JSONQuery是JSONPath的超集,因此在dojo中取代了它。此外还有RQL

来自Dojo文档:

JSONQuery是JSONPath的扩展版本,具有额外的功能,包括安全性、易用性和全面的数据查询工具,包括过滤、递归搜索、排序、映射、范围选择和灵活的表达式,具有通配符字符串比较和各种运算符。

JSONselect在这个问题上有另一种观点(类似于CSS选择器而不是XPath),并且有一个JavaScript实现


4
GitHub上的JSONQuery链接似乎已经失效了。而且现在JSONSelect也有一个JavaScript版本。 - Henrik Aasted Sørensen

21
我知道的其他选择包括:
  1. JSONiq规范,它指定了两种子类型的语言:一种隐藏XML细节并提供类似JS的语法,另一种以JSON构造函数等丰富XQuery语法。 Zorba实现了JSONiq。
  2. Corona建立在MarkLogic之上,为存储、管理和搜索XML、JSON、文本和二进制内容提供REST接口。
  3. MarkLogic 6及更高版本提供类似于Corona的REST接口。
  4. MarkLogic 8及更高版本在其XQuery和服务器端JavaScript环境中都原生支持JSON。你可以对其应用XPath。
希望这能帮到你。

3
现在有一个JSONiq实现:Zorba 2.6已经正式支持它。 - Ghislain Fourny
注意:MarkLogic自版本8起原生存储JSON,并允许直接在其上应用XPath。 - grtjn

16
尝试使用JSPath JSPath是一种领域特定语言(DSL),可让您在JSON文档中导航和查找数据。使用JSPath,您可以选择JSON项以检索它们所包含的数据。
JSPath for JSON类似于XPath for XML。
它在Node.js和现代浏览器上都进行了大量优化。

12

是否有某种查询语言...

jq 定义了一种与 JSONPath 非常相似的JSON query 语言,详情请参见 https://github.com/stedolan/jq/wiki/For-JSONPath-users

...我可以用它来查找[0].objects中 id = 3 的项目吗?

我会假设这意味着:在指定的键下查找所有 id == 3 的 JSON 对象,无论对象在哪里。 相应的jq查询如下:

.[0].objects | .. | objects | select(.id==3)

其中“|”是管道运算符(如命令行shell中的管道),而段落“.. | objects”对应于“无论对象在哪里”。

jq的基础知识通常很明显、直观或至少相当简单,如果您对命令行shell管道有所了解,那么大多数其他内容都很容易掌握。 jq FAQ 提供了指向教程等的指针。

与SQL类似,jq也支持CRUD操作,但jq处理器永远不会覆盖其输入。jq还可以处理JSON实体流。

在评估面向JSON的查询语言时,您可能希望考虑另外两个标准:

  • 它是否支持正则表达式?(jq 1.5提供了PCRE正则表达式的全面支持)
  • 它是否是图灵完备的?(是的)

10

10

XQuery可以用于查询JSON,前提是处理器提供了JSON支持。这是一个很简单的例子,演示了如何使用BaseX查找具有“id” = 1的对象:

json:parse('[
    { "id": 1, "name": "One", "objects": [
        { "id": 1, "name": "Response 1", "objects": [ "etc." ] }
    ]}
]')//value[.//id = 1]

(6年后)Saxon将运行查询JSON的XQuery 3.1。我的Saxon经验是使用Java运行jar文件。有一个名为saxon-java的节点模块,但我不确定它如何与json一起工作。还有来自Saxonica的另一个新东西叫做Saxon-JS。 - charles ross

9

Defiant.js 看起来也很酷,这里有一个简单的例子:

var obj = {
        "car": [
            {"id": 10, "color": "silver", "name": "Volvo"},
            {"id": 11, "color": "red",    "name": "Saab"},
            {"id": 12, "color": "red",    "name": "Peugeot"},
            {"id": 13, "color": "yellow", "name": "Porsche"}
        ],
        "bike": [
            {"id": 20, "color": "black", "name": "Cannondale"},
            {"id": 21, "color": "red",   "name": "Shimano"}
        ]
    },
    search = JSON.search(obj, '//car[color="yellow"]/name');

console.log( search );
// ["Porsche"]

var reds = JSON.search(obj, '//*[color="red"]');

for (var i=0; i<reds.length; i++) {
    console.log( reds[i].name );
}
// Saab
// Peugeot
// Shimano

很遗憾,目前还没有在npm上发布,需要手动安装... - Andrew Mao

8

Jsel非常棒,它基于真正的XPath引擎。它允许您创建XPath表达式来查找任何类型的JavaScript数据,而不仅仅是对象(也包括字符串)。

您可以创建自定义模式和映射,完全控制XPath引擎如何遍历您的数据。模式是定义元素、子元素、属性和节点值在您的数据中如何定义的一种方式。然后,您可以创建自己的表达式来适应。

假设您有一个名为data的变量,其中包含问题中的JSON,您可以使用jsel编写:

jsel(data).select("//*[@id=3]")

这将返回任何具有 id 属性为3的节点。属性是对象中的任何原始(字符串、数字、日期、正则表达式)值。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接