有没有用于JSON的查询语言?

260

是否有一种类似于SQL或XQuery的语言来查询JSON?

我考虑到非常小的数据集可以很好地映射到JSON,因此很容易回答查询问题,例如“在Y> 3的情况下,X的所有值是什么”,或者进行通常的SUM / COUNT类型操作。

举个编造的例子,像这样:

[{"x": 2, "y": 0}}, {"x": 3, "y": 1}, {"x": 4, "y": 1}]

SUM(X) WHERE Y > 0     (would equate to 7)
LIST(X) WHERE Y > 0    (would equate to [3,4])

我认为这个方法可以在客户端和服务器端同时使用,结果将被转换为适当的语言特定数据结构(或保留为JSON)。快速搜索表明人们已经考虑并实现了一些东西(JAQL),但似乎还没有出现标准用法或一组库。虽然每个函数本身都相当简单易行,但如果有人已经做对了,我就不想重复发明轮子。有什么建议吗?
编辑:这可能确实是一个坏主意,或者JSON可能过于通用了。之所以希望有一个查询语言而不是直接根据需要执行求和/等函数,是因为我希望根据用户输入动态构建查询。有点像“我们不需要SQL,我们可以直接编写我们需要的函数”的说法。最终,要么变得无法控制,要么你会随着推进而编写自己的SQL版本。(好吧,我知道这有点儿荒谬,但你懂我的意思..)

我也有这样的需求。我需要通过对象树中特定位置的特定值来匹配传入的JSON请求。查询实际上必须由(强大的)用户配置。当前的解决方法是将JSON构建为临时XML并应用XPath。 - Vladimir Dyuzhev
4
它更像是一个命令行工具,但 jq (https://stedolan.github.io/jq/) 可以很好地探索 JSON 数据。你可以在 playground (https://jqplay.org/) 上试试它。 - jtmoulia
有一个基于网络的工具,可以让你在公共JSON源或API上运行SQL查询,网址为sqall.co - Stack Man
参见:https://dev59.com/x1vUa4cB1Zd3GeqPy_1D https://dev59.com/x1vUa4cB1Zd3GeqPy_1D#16508328 - dreftymac
更多想法请访问 https://dev59.com/3HI-5IYBdhLWcg3wO1vl - wisbucky
有人能否编制一个与平台或语言相关的JSON查询语言列表?例如,JMespath适用于kubernetesaws使用athena,而它可能适用于arm template吗? - Rajesh Swarnkar
27个回答

113

编辑于2022年9月:

JMESPath似乎是这方面最广泛使用、增长最快评价最好的替代品。它具有许多功能,包括“where”样式过滤器

原文:

当然可以,比如:

它们都似乎还在不断完善中,但某种程度上已经可以使用。它们在概念上也类似于XPath和XQuery,尽管XML和JSON具有不同的概念模型(分层结构 vs 对象/结构体)。

编辑于2015年9月:

实际上,现在有JSON Pointer标准,可以非常简单和高效地遍历JSON内容。它不仅被正式规定,而且也被许多JSON库支持。因此,我认为它是一个真正有用的标准,尽管由于其有限的表达能力,它可能或可能不被认为是查询语言本身。


89
换言之,没有标准和稳定的东西...... :-( - Vladimir Dyuzhev
2
说到标准,我听说 XQuery 3.1 可能会扩展支持 JSON 查询(类似于 JSONiq)。当然,这可能需要一些时间,因为 XQuery 3.0 还没有正式发布。 - Julien Ribon
哦,天哪,我绝对希望不是这样。我见过的所有XML->JSON尝试都是一团糟--信息模型不兼容。但我想看到JQuery使用相同的思想、语法部分;只是适当修改为JSON信息模型。 - StaxMan
1
寻找 Ruby 的 JSONPath 实现的人可以访问以下链接: https://github.com/joshbuddy/jsonpath - Robert Ross
@GôTô:如果你有这个自由,使用MongoDB似乎是一个可行的方法。(请参见下面的答案,了解如何将查询转换为内置shell的示例) - serv-inc

52

UNQL已经是一个废弃的域名,很可能也是一个废弃的项目。 - Xdg
有没有可能通过哪种查询语言来指示流行的公司?例如,微软Azure的azure-cli使用了JMESPathkubectljqjsonpath搭配得很好。 - Rajesh Swarnkar
看起来大多数都已经停止维护了,至少在Node方面是这样。最近更新的是JMESpath。 - undefined

50

我建议使用我正在开发的名为jLinq的项目。我正在寻求反馈,所以我很想听听你的想法。

它让你编写类似于LINQ的查询...

var results = jLinq.from(records.users)

    //you can join records
    .join(records.locations, "location", "locationId", "id")

    //write queries on the data
    .startsWith("firstname", "j")
    .or("k") //automatically remembers field and command names

    //even query joined items
    .equals("location.state", "TX")

    //and even do custom selections
    .select(function(rec) {
        return {
            fullname : rec.firstname + " " + rec.lastname,
            city : rec.location.city,
            ageInTenYears : (rec.age + 10)
        };
    });

它也是完全可扩展的!

文档仍在更新中,但您仍然可以在线尝试它。


@hugoware:这个有没有文档介绍呢?除了 .starts() 之外还有其他查询方法吗,比如 contains - Rikki
8
最后更新于8年前,5年前曾询问项目是否已停止,但没有回复...我认为这个项目已经死了。 - cfc
1
是的,似乎已经死了。链接现在是404。JMESPath似乎非常强大、标准化和跨平台,但不确定它是否像jLinq一样可以进行连接操作。 - Simon East

20

JMESPath非常易于使用,而且效果很好:http://jmespath.org/。它有一个详细的规范以及多种语言的库。亚马逊在AWS命令行界面中使用它,因此它非常稳定。

语法示例:

// 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(', ', @)

你可以在文档中找到更多实时示例可供使用。


6
在同一页上,文档中也写道:“如果你需要更高级的功能而 --query 无法满足,你可以尝试 jq,一个命令行 JSON 处理器。”因此看起来 AWS 在 --query 参数中使用了 jmespath,但建议使用 jq 进行命令行管道操作。http://docs.aws.amazon.com/cli/latest/userguide/controlling-output.html - wisbucky
+1 for JMESPath - 它是一个非常全面和详细的规范,具有多种语言的库和相对简单直观的语法。 - Simon East

19

jq是一种JSON查询语言,主要用于命令行,但可以绑定到各种编程语言(Java、node.js、PHP等),甚至可以通过jq-web在浏览器中使用。jq的基于C的实现通常称为"jq",基于Go的版本则称为"gojq"

以下是一些基于原始问题的说明,该问题提供了这个JSON作为示例:

 [{"x": 2, "y": 0}}, {"x": 3, "y": 1}, {"x": 4, "y": 1}]

SUM(X) WHERE Y > 0 (等同于7)

map(select(.y > 0)) | add

当Y > 0时,LIST(X)等同于[3,4]。

map(.y > 0)

jq语法扩展了JSON语法

每个JSON表达式都是合法的jq表达式,例如[1, (1+1)]和{"a": (1+1)}说明了jq如何扩展JSON语法。

一个更有用的例子是jq表达式:

{a,b}

给定 JSON 值 {"a":1, "b":2, "c": 3},返回的值是{"a":1, "b":2}


10
内置的array.filter()方法使得大多数所谓的JavaScript查询库都过时了。
您可以在委托中放置尽可能多的条件:简单比较、startsWith等。我还没有测试过,但您可能也可以嵌套过滤器以查询内部集合。

6
array.filter() 是 JavaScript 的一部分,而不是 JSON。 - Iain Samuel McLean Elder
2
JSON是JavaScript的子集,但有很多语言都支持JSON和数组,并且实现了数组过滤方法,因此这是一个有效的观点。 - dakab
虽然你的答案是正确的,即filter()可以用于“查询”JSON对象,但有一个缺点:它接受函数而不是字符串。因此,你不能在网络上使用它作为参数传递。 - iaforek

8

另一种思考方式是使用mongoDB。您可以将JSON存储在mongo中,然后通过mongodb查询语法进行查询。


MongoDB使用起来非常好。请参考以下示例以了解如何使用:链接 - serv-inc
1
正要建议同样的事情。https://docs.mongodb.com/manual/tutorial/query-documents/ - Denise Skidmore

7

ObjectPath是一种用于查询复杂或未知结构JSON文档的简单轻量级查询语言。它类似于XPath或JSONPath,但由于嵌入算术计算、比较机制和内置函数等功能而更加强大。

Example

Python版本已经成熟并用于生产。JS仍处于beta版。
可能在不久的将来我们将提供一个完整的Javascript版本。我们还希望进一步开发它,使其成为Mongo查询的更简单的替代方案。

1
除了几乎没有文档,所以很难找到如何做任何事情,比如查找文本为某个值的元素。 - James O'Brien
1
@JamesO'Brien 感谢您的评论 - 如果您发现参考文献没用,或者有任何具体问题,请在这里告诉我们[https://groups.google.com/forum/#!forum/objectpath] - 会有人尝试帮助。我们正在努力使文档更易用,我很想听听您的意见。 - Ela Bednarek
谢谢 - 我很感激。我想使用。目前我正在使用http://ashphy.com/JSONPathOnlineEvaluator/? - James O'Brien
由于完全缺乏文档,我无法弄清如何在Javascript中使用它。 - user3670743
我们正在寻找贡献者来帮助完成这项工作。您可以在Github或Google Groups https://groups.google.com/forum/#!members/objectpath 上写下您想要实现的内容,我相信会有人回答您的问题。 - Ela Bednarek

7
如果您正在使用.NET,那么Json.NET支持对JSON进行LINQ查询。这个文章有一些示例。它支持过滤、映射、分组等功能。

4

好的,这篇文章有点旧了,但是...如果你想在JS对象或本地JSON中执行类似SQL的查询,可以看一下https://github.com/deitch/searchjs

它既是一个完全用JSON编写的jsql语言,也是一个参考实现。你可以这样说,“我想查找数组中所有名字为“John”且年龄为25岁的对象:

{name:"John",age:25,_join:"AND"}

参考实现searchjs既可以在浏览器中使用,也可作为Node npm包使用。
npm install searchjs

它还可以执行复杂的连接和否定(NOT)等操作。它本身会忽略大小写。

它目前还不支持求和或计数,但在外部进行这些操作可能更容易。


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