ChatGPT解决这个技术问题 Extra ChatGPT

是否有与 XQuery/XPath 等效的 JSON?

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

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

是否有某种查询语言可用于查找项目 in [0].objects where id = 3

除非你做一个。将查询留给服务器,并使用 REST 仅获取您需要的数据。
+1 好主意。明天写这个……
不是 XPath,但我发现 JLinq 非常好(它使代码读起来像 in(...).where(...).select(...)):hugoware.net/Projects/jLinq
这令人沮丧,因为那里有很多库,但没有任何东西接近普遍接受的标准。我们有一个第三方使用的库,因此我们需要提供一种广为人知和使用的查询语言。
当然,您可以使用 jsel - github.com/dragonworx/jsel - 假设您有一个包含 JSON 对象的变量 data,您可以编写:jsel(data).select("//*[@id=3]"),它会返回包含 id 键为 3 的对象。

M
Mike Christensen

是的,它被称为 JSONPath

它也集成到 DOJO 中。


Brian 的回答建议 jsonQuery 模块应该在 dojo 中使用 jsonPath 模块的instead
这有多结实?而且我找不到对我们来说是交易杀手的 Java 或 C# 版本。
此处链接的站点提供 Javascript 和 PHP。如果您需要 Java 实现,这里有一个:code.google.com/p/json-path
我应该提到 JSONPath 不是基于 XPath 形式语义的。 JSONiq 可能是一个更好的选择。
@Paramaeleon 效果很好。顺便说一下,该项目是 migrated to GitHub。迈克可能想将此添加到答案中,因为人们一直对此发表评论。
S
Simon East

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

您可以在 the docs 中使用更多实时示例。

JS 库缩小了 19kb,因此可能比某些库大,但考虑到广泛的功能,您可能会觉得值得。

其他选项

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

JSPath .automobiles{.maker === "本田" && .year > 2009}.model

json:select() (更多灵感来自 CSS 选择器) .automobiles .maker:val("Honda") .model

JSONPath(更多灵感来自 XPath)$.automobiles[?(@.maker='Honda')].model


很棒的总结和例子,也是因为提到了在 CSS 选择器或 XPath 中找到的灵感。
l
lorey

我认为 JSONQuery 是 JSONPath 的超集,因此是 replaces it in dojo。然后还有RQL

来自 Dojo 文档:

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

JSONselect 对问题有另一种观点(类似于 CSS 选择器,而不是 XPath)并有一个 JavaScript implementation


github JSONQuery 链接似乎已死。 JSONSelect 现在也有一个 JavaScript 版本。
g
grtjn

我知道的其他选择是

JSONiq 规范,它指定了两种语言子类型:一种隐藏 XML 细节并提供类似 JS 的语法,另一种使用 JSON 构造函数等丰富 XQuery 语法。 Zorba 实现 JSONiq。 Corona 建立在 MarkLogic 之上,提供了一个 REST 接口,用于存储、管理和搜索 XML、JSON、文本和二进制内容。 MarkLogic 6 及更高版本提供了与 Corona 类似的开箱即用的 REST 接口。 MarkLogic 8 及更高版本在其 XQuery 和服务器端 JavaScript 环境中都原生支持 JSON。您可以在其上应用 XPath。

HTH。


现在有一个 JSONiq 实现:Zorba 2.6 正式支持它。
注意:MarkLogic 从版本 8 开始本地存储 JSON,并允许直接在其上应用 XPath。
d
dfilatov

尝试使用 JSPath

JSPath 是一种特定于域的语言 (DSL),它使您能够在 JSON 文档中导航和查找数据。使用 JSPath,您可以选择 JSON 项目以检索它们包含的数据。

JSON 的 JSPath 类似于 XML 的 XPath。

它针对 Node.js 和现代浏览器进行了大量优化。


p
peak

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

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

... [which] 我可以用来在 [0].objects 中找到 id = 3 的项目?

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

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

其中“|”是管道运算符(如在命令外壳管道中),并且段“.. | objects”对应于“无论对象可能在哪里”。

jq 的基础知识在很大程度上是显而易见的或直观的,或者至少非常简单,如果您完全熟悉命令外壳管道,那么其余的大部分内容都很容易掌握。 jq FAQ 有指向教程等的指针。

jq 也与 SQL 类似,因为它支持 CRUD 操作,尽管 jq 处理器从不覆盖其输入。 jq 还可以处理 JSON 实体流。

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

它支持正则表达式吗? (jq 1.5 全面支持 PCRE 正则表达式)

它是图灵完备的吗? (是的)


C
Christian Grün

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 将运行 XQuery 3.1,它查询 JSON。我的撒克逊经验是使用 java 运行的 jar 文件。有一个名为 saxon-java 的节点模块,但我不确定 w/json 是如何工作的。还有一个来自 Saxonica 的新东西,叫做 Saxon-JS。
C
Community

Json Pointer 似乎也获得了越来越多的支持。


E
Epoc

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 上发布,需要手动安装......
A
Ali

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

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

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

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

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


d
dimo414

ObjectPath 是一种类似于 XPath 或 JSONPath 的查询语言,但由于嵌入式算术计算、比较机制和内置函数而更加强大。见语法:

在商店中找到所有红色且价格低于 50 的鞋子

$..shoes.*[颜色为“红色”且价格 < 50]


我喜欢网站上的第一个示例,ObjectPath 可以在交互的、类似 shell 的模式下运行非常棒,但我正在寻找的是在 Python 脚本中使用 ObjectPath。你能给我举个例子来展示如何使用 ObjectPath 作为库吗?我在网站上找不到类似的东西。
请参阅 github 上有关 Python 使用的部分。我们将把它添加到网站上——目前确实很难找到。如果您需要任何进一步的帮助,您可以在 google group 上发布问题。
谢谢 Ela,github 页面上添加的示例正是需要的。
j
jlh

JMESPath 如今(截至 2020 年)似乎很受欢迎,并解决了 JSONPath 的许多问题。它适用于多种语言。


是的,它看起来非常清晰和干净,语法非常接近标准 JavaScript,并且跨多种语言标准化。 👍
H
Hakan Bilgin

@Naftule - 使用“defiant.js”,可以使用 XPath 表达式查询 JSON 结构。查看此评估器以了解其工作原理:

http://www.defiantjs.com/#xpath_evaluator

与 JSONPath 不同,“defiant.js”提供了对查询语法的全面支持——对 JSON 结构的 XPath。

defiant.js 的源代码可以在这里找到:
https://github.com/hbi99/defiant.js


M
Michael Kay

只是为了增加选择,还有 XPath。 XPath 3.1 处理 JSON 以及 XML。在 XPath 3.1 中,您需要的查询是 ?0?Objects?*[?id=3]


l
leo60228

latest XPath spec 包括 JSON 支持:

XPath 的主要目的是处理 XML 树和 JSON 树的节点。 XPath 得名于它使用路径表示法在 XML 文档的层次结构中导航。 XPath 使用紧凑的非 XML 语法来促进在 URI 和 XML 属性值中使用 XPath。 XPath 3.1 为导航 JSON 树添加了类似的语法。

XQuery 也是如此:

JSON 是一种轻量级的数据交换格式,广泛用于在 Web 上交换数据并将数据存储在数据库中。许多应用程序将 JSON 与 XML 和 HTML 一起使用。 XQuery 3.1 扩展了 XQuery 以支持 JSON 和 XML,将映射和数组添加到数据模型中,并使用语言中的新表达式和 [XQuery 和 XPath 函数和运算符 3.1] 中的新函数来支持它们。


a
adittes

如果您像我一样只想进行基于路径的查找,而不关心真正的 XPath,那么 lodash 的 _.get() 可以工作。来自 lodash 文档的示例:

var object = { 'a': [{ 'b': { 'c': 3 } }] };

_.get(object, 'a[0].b.c');
// → 3

_.get(object, ['a', '0', 'b', 'c']);
// → 3

_.get(object, 'a.b.c', 'default');
// → 'default'

不幸的是,该函数只能返回一个结果,它不支持获取匹配项的数组,这是其他库的亮点。
S
Satyajit Paul

试试这个 - https://github.com/satyapaul/jpath/blob/master/JSONDataReader.java

这是在 xml 的类似 xpath 行上的一个非常简单的实现。它的名称为 jpath。


此问题已标记为 javascript,但此库似乎适用于 java
它也有 Javascript 版本 - github.com/satyapaul/jpath/blob/master/jpath.js 这是他的项目的 git 主页 - github.com/satyapaul/jpath
р
рüффп

我知道 OP 用 javascript 标记了这个问题,但就我而言,我看起来完全一样,但来自 Java 后端(使用 Camel)。

如果您使用像 Camel 这样的集成框架,那么有趣的事情也很有用,自 Camel 2.13 起,特定的 Camel Component 也支持 jsonPath

来自上述骆驼文档的示例:

from("queue:books.new")
  .choice()
    .when().jsonpath("$.store.book[?(@.price < 10)]")
      .to("jms:queue:book.cheap")
    .when().jsonpath("$.store.book[?(@.price < 30)]")
      .to("jms:queue:book.average")
    .otherwise()
      .to("jms:queue:book.expensive")

使用起来非常简单。