
JSONPath v10.4.1
JSONPath 的一个分支,源自 http://goessner.net/articles/JsonPath/
(另请参阅 开发依赖的许可证)
JSONPath Plus
分析、转换并从 JSON 文档(以及 JavaScript 对象)中选择性地提取数据。
jsonpath-plus 在原始规范的基础上进行了扩展,新增了一些额外的运算符,并明确了原始规范未明确说明的一些行为。
试试浏览器演示或 Runkit (Node)。
请注意:本项目目前没有积极维护。我们可能会接受有良好文档的 PR 或一些简单的更新,但不打算自行修复问题或添加新功能。
功能
- 符合原始 jsonpath 规范
- 原始规范未提供的便捷添加或补充:
^用于获取匹配项的父级~用于获取匹配项的属性名(以数组形式)- 类型选择器,用于获取:
- 基本 JSON 类型:
@null()、@boolean()、@number()、@string()、@array()、@object() @integer()- 复合类型
@scalar()(在查询 JavaScript 对象时,它还接受undefined和非有限数字,以及所有基本的非对象/非函数类型) @other()可与用户定义的otherTypeCallback结合使用- 查询非 JSON JavaScript 对象时仍可使用的非 JSON 类型(
@undefined()、@function()、@nonFinite())
- 基本 JSON 类型:
- 过滤器中的
@path/@parent/@property/@parentProperty/@root简写选择器 - 转义
`用于转义剩余序列@['...']/?@['...']语法用于转义过滤器中属性名内的特殊字符
- 记录
$..(获取所有父级组件)
- ESM 和 UMD 导出格式
- 除了查询到的值之外,还能返回各种元信息,包括值的路径或指针,以及父对象和父属性名(以便进行修改)。
- 用于在路径、数组和指针之间进行转换的工具
- 可选阻止评估原始规范中允许的表达式,或为被评估的值提供沙箱。
- 可选回调函数,在获取结果时进行处理。
基准测试
根据 json-querying-performance-testing,与其他 json 查询库相比,jsonpath-plus 在处理大型和小型数据集时都表现稳定。您可以通过自行运行该项目并添加更多性能测试用例来验证这些发现。
安装```shell
npm install jsonpath-plus
## 设置
### Node.js```js
const {JSONPath} = require('jsonpath-plus');
const result = JSONPath({path: '...', json});
浏览器
对于浏览器使用,你可以直接包含 dist/index-browser-umd.cjs;无需
任何 Browserify 魔法:```html
### ESM(现代浏览器)
您也可以使用 ES6 模块导入(适用于现代浏览器):```html
<script type="module">
import {
JSONPath
} from './node_modules/jsonpath-plus/dist/index-browser-esm.js';
const result = JSONPath({path: '...', json: {}});
</script>
ESM (打包器)
或者,如果你正在打包你的 JavaScript(例如,使用 Rollup),只需使用,
注意 mainFields
应包含 browser 用于浏览器构建(对于 Node,默认情况下,
检查 module,应该没问题):```js
import {JSONPath} from 'jsonpath-plus';
const result = JSONPath({path: '...', json});
## 用法
可用完整签名如下:```
const result = JSONPath([options,] path, json, callback, otherTypeCallback);
参数 path、json、callback 和 otherTypeCallback
也可以(连同任何其他可用属性)在 options
上表达。
请注意,result 将包含找到的所有项(可选择
包装到数组中),而 callback 可用于在
发现每个项时执行某些操作,
回调函数将根据结果中独立项的数量
执行 0 到 N 次。
有关 JSONPath 可用参数的更多信息,请参阅下面的文档。
另请参阅 API 文档。
属性
可以在 options 对象或 evaluate 方法(作为第一个参数)上提供的属性包括:
- path(必需) - 作为(规范化 或非规范化)字符串或数组的 JSONPath 表达式
- json(必需) - 要求值的 JSON 对象(可以是 null、布尔值、数字、字符串、对象或数组类型)。
- autostart(默认值:true) - 如果将其提供为
false, 则可以手动调用evaluate方法。 - flatten(默认值:false) - 返回的结果数组 是否会被展平为单维数组。
- resultType(默认值:"value") - 可以是 "value"、"path"、"pointer"、"parent" 或 "parentProperty" 的不区分大小写形式,用于确定 分别是否将结果作为找到项的值、作为其绝对路径、作为 JSON 指针 指向绝对路径、作为其父对象,还是作为其父对象的 属性名返回。如果设置为 "all",则所有这些类型都将返回在 一个对象上,并以类型作为键名。
- sandbox(默认值:{}) - 键值对映射,其中的变量可用于 代码求值(如过滤表达式)。(请注意, 当前路径和值也将可用于这些 表达式;有关详细信息,请参阅语法部分。)
- wrap(默认值:true) - 是否将结果包装在数组中。如果
wrap设置为false, 且没有找到结果,则将返回undefined(而当wrap设置为 true 时,则返回空数组)。 如果wrap设置为false且找到单个非数组结果,则只返回该结果 (不在数组中)。不过,如果找到多个结果,仍将返回一个数组。 为避免歧义(在需要区分某个结果是失败还是空数组的情况下), 建议将默认值改为false。 - eval(默认值:"safe") - 脚本求值方法。
safe:在浏览器中,它将使用一个极简的脚本引擎,该引擎不使用eval或Function,并满足内容安全策略。在 NodeJS 中, 它没有效果,等同于native,因为在那里脚本是安全的。native:使用原生脚本能力。即在浏览器中使用不安全的eval或Function,在 nodejs 中使用vm.Script。false:禁用 JavaScript 求值表达式,并在尝试这些表达式时抛出异常。callback [ (code, context) => value]:一个自定义实现,调用时以code和context作为参数,返回求值后的值。class:一个以code作为构造函数参数创建的类,代码通过使用context调用runInNewContext来求值。 `` - ignoreEvalErrors(默认值:false) - 忽略脚本求值期间 遇到的错误。
- parent(默认值:null) - 如果某个查询可能被 设置为返回根节点,此选项允许将根节点的父节点 在结果中返回。
- parentProperty(默认值:null) - 如果某个查询
可能被设置为返回根节点,此选项允许在结果中返回
该根节点的
parentProperty。这可以是字符串 属性名或数字数组索引。 - callback(默认值:(无)) - 如果提供,则在
检索到端点值后立即调用回调。提供的三个参数
将是有效载荷的值(根据
resultType)、 有效载荷的类型(是普通的 "value" 还是 "property" 名称),以及完整的有效载荷对象(包含所有resultType)。 - otherTypeCallback(默认值:<一个抛出错误的函数
,当遇到 @other() 时>) - 在目前缺乏 JSON
Schema 支持的情况下,可以通过在查询末尾
添加运算符
@other()来确定内置类型之外的类型。如果遇到这样的 路径,则将使用项目的值、其路径、其父对象及其父对象的属性名 来调用otherTypeCallback, 并且它应返回一个布尔值,指示所提供的值 是否属于 "other" 类型(或者它可以处理转换并 返回 false)。
实例方法
- evaluate(path, json, callback, otherTypeCallback) OR
evaluate({path: <path>, json: <json object>, callback:
<callback function>, otherTypeCallback:
<otherTypeCallback function>}) - 仅当
autostart属性设置为false时才需要 此方法。它可用于使用相同配置重复求值。 除了列出的属性外,后一种方法形式可以 接受任何其他允许的实例属性(除了autostart,因为它在这里没有相关性)。
类属性与方法
- JSONPath.clearCache() - 清除内部缓存的已解析路径和 编译后的脚本。缓存内容不会暴露;当需要使缓存 失效时,调用此方法。
- JSONPath.toPathArray(pathAsString) - 接受规范化或
非规范化的路径字符串,并将其转换为数组:例如,
['$', 'aProperty', 'anotherProperty']。 - JSONPath.toPathString(pathAsArray) - 接受路径数组并
将其转换为规范化路径字符串。该字符串的形式将类似于:
$['aProperty']['anotherProperty][0]。JSONPath 的终端 结构~和^以及像@string()这样的类型运算符会被 静默剥离。 - JSONPath.toPointer(pathAsArray) - 接受路径数组并
将其转换为 JSON 指针。
该字符串的形式将类似于:
/aProperty/anotherProperty/0(任何内部的~和/字符都按照 JSON 指针规范进行转义)。 JSONPath 的终端结构~和^以及 像@string()这样的类型运算符会被静默剥离。
通过示例了解语法
给定以下 JSON,取自 http://goessner.net/articles/JsonPath/:```json { "store": { "book": [ { "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95 }, { "category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.99 }, { "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "isbn": "0-553-21311-3", "price": 8.99 }, { "category": "fiction", "author": "J. R. R. Tolkien", "title": "The Lord of the Rings", "isbn": "0-395-19395-8", "price": 22.99 } ], "bicycle": { "color": "red", "price": 19.95 } } }
以及以下 XML 表示形式:```xml
<store>
<book>
<category>reference</category>
<author>Nigel Rees</author>
<title>Sayings of the Century</title>
<price>8.95</price>
</book>
<book>
<category>fiction</category>
<author>Evelyn Waugh</author>
<title>Sword of Honour</title>
<price>12.99</price>
</book>
<book>
<category>fiction</category>
<author>Herman Melville</author>
<title>Moby Dick</title>
<isbn>0-553-21311-3</isbn>
<price>8.99</price>
</book>
<book>
<category>fiction</category>
<author>J. R. R. Tolkien</author>
<title>The Lord of the Rings</title>
<isbn>0-395-19395-8</isbn>
<price>22.99</price>
</book>
<bicycle>
<color>red</color>
<price>19.95</price>
</bicycle>
</store>
请注意,以下 XPath 示例并不区分
检索元素与其文本内容(除非为了
比较或防止歧义而有必要)。注意:要测试这些 XPath 示例
(包括 2.0 示例),这个演示
可能会有所帮助(设置为 xml 或 xml-strict)。| XPath | JSONPath | 结果 | 说明 |
|-------------------------------------------------------------------------------------|---------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| /store/book/author | $.store.book[*].author | store 中所有书籍的作者 | 也可以不带 $. 表示为 store.book[*].author(虽然这并未出现在原始规范中);不过请注意,某些字符字面量($ 和 @)需要转义 |
| //author | $..author | 所有作者 | |
| /store/* | $.store.* | store 中的所有东西,即它的书籍(一个书籍数组)和一辆红色自行车(一个自行车对象) | |
| /store//price | $.store..price | store 中所有东西的价格 | |
| //book[3] | $..book[2] | 第三本书(书籍对象) | |
| //book[last()] | $..book[(@.length-1)]
$..book[-1:] | 按顺序排列的最后一本书 | 要访问带有特殊字符的属性,请使用 [(@['...'])] 作为过滤器(此特定功能未出现在原始规范中) |
| //book[position()<3] | $..book[0,1]
$..book[:2] | 前两本书 | |
| //book/*[self::category\|self::author] 或 //book/(category,author)(在 XPath 2.0 中) | $..book[0][category,author] | 所有书籍的类别和作者 | |
| //book[isbn] | $..book[?(@.isbn)] | 过滤所有带有 ISBN 编号的书籍 | 要访问带有特殊字符的属性,请使用 [?@['...']] 作为过滤器(此特定功能未出现在原始规范中) |
| //book[price<10] | $..book[?(@.price<10)] | 过滤所有价格低于 10 的书籍 | |
| //*[name() = 'price' and . != 8.95] | $..*[?(@property === 'price' && @ !== 8.95)] | 获取所有属性为 price 且值不等于 8.95 的对象的所有属性值 | 使用裸 @ 可以按属性值过滤对象(不一定要在数组内),你可以在表达式后添加 ^ 来获取拥有被过滤属性的对象 |
| / | $ | JSON 对象的根(即整个对象本身) | 要获取字面量 $(单独使用或在路径中的任意位置),必须使用反引号转义 |
| //*/*\|//*/*/text() | $..* | XML 文档中根节点下的所有元素(和文本)。JSON 结构中根节点下的所有成员。 | |
| //* | $.. | XML 文档中的所有元素。JSON 结构中包括根在内的所有父级组件。 | 此行为在原始规范中没有直接规定 |
| //*[price>19]/.. | $..[?(@.price>19)]^ | 价格大于 19 的那些特定项的父级(即 store 值是 bicycle 的父级,book 数组是单本书的父级) | 父级(脱字符)未出现在原始规范中 |
| /store/*/name()(在 XPath 2.0 中) | $.store.*~ | store 子对象("book" 和 "bicycle")的属性名称。与通配符属性一起使用时很有用。 | 属性名称(波浪号)未出现在原始规范中 |
| /store/book[not(. is /store/book[1])](在 XPath 2.0 中) | $.store.book[?(@path !== "$['store']['book'][0]")] | 除位于指向第一本书的路径上的那本书之外的所有书籍 | @path 未出现在原始规范中 |
| //book[parent::*/bicycle/color = "red"]/category | $..book[?(@parent.bicycle && @parent.bicycle.color === "red")].category | 获取所有此类书籍的类别:书籍的父对象有一个颜色为红色的 bicycle 子对象(即所有书籍) | @parent 未出现在原始规范中 |
| //book/*[name() != 'category'] | $..book.*[?(@property !== "category")] | 获取 "book" 的所有子项,但 "category" 类型的子项除外 | @property 未出现在原始规范中 |
| //book[position() != 1] | $..book[?(@property !== 0)] | 获取所有属性(由于我们在数组内部进行访问,该属性是数字索引)不为 0 的书籍 | @property 未出现在原始规范中 |
| /store/*/*[name(parent::*) != 'book'] | $.store.*[?(@parentProperty !== "book")] | 获取 store 的孙级节点,这些节点的父级属性不是 book(即 bicycle 的子项:"color" 和 "price") | @parentProperty 未出现在原始规范中 |
| //book[count(preceding-sibling::*) != 0]/*/text() | $..book.*[?(@parentProperty !== 0)] | 获取所有书籍实例的属性值,其中这些值的父级属性(即保存书籍条目父对象的数组索引)不为 0 | @parentProperty 未出现在原始规范中 |
| //book[price = /store/book[3]/price] | $..book[?(@.price === @root.store.book[2].price)] | 过滤所有价格等于第三本书价格的书籍 | @root 未出现在原始规范中 |
| //book/../*[. instance of element(*, xs:decimal)](在 XPath 2.0 中) | $..book..*@number() | 获取 book 数组中的数值 | @number()、其他基本类型(@boolean()、@string())、其他底层派生类型(@null()、@object()、@array())、JSONSchema 新增的类型 @integer()、复合类型 @scalar()(它也接受 undefined 和非有限数,适用于 JavaScript 对象以及所有基本的非对象/非函数类型)、需要与用户自定义回调一起使用的类型 @other()(参见 otherTypeCallback),以及以下在查询非 JSON JavaScript 对象时仍可与 JSONPath 一起使用的非 JSON 类型(@undefined()、@function()、@nonFinite())均未出现在原始规范中 |
| //book/*[name() = 'category' and matches(., 'tion$')](XPath 2.0) | $..book.*[?(@property === "category" && @.match(/TION$/i))] | 匹配正则表达式(以 'TION' 结尾,不区分大小写)的所有书籍类别 | @property 未出现在原始规范中。 |
| //book/*[matches(name(), 'bn$')]/parent::*(XPath 2.0) | $..book.*[?(@property.match(/bn$/i))]^ | 所有拥有匹配正则表达式(以 'TION' 结尾,不区分大小写)的属性的书籍 | @property 未出现在原始规范中。注意:在表达式末尾使用父级选择器 ^ 可返回到父对象;如果没有父级选择器,它将匹配两个 isbn 键值。 |
| | `(例如, `$ 用于匹配字面名称为 $ 的属性) | 转义其后的整个序列(将其视为字面量) | ` 未出现在原始规范中;要获取字面量反引号,请使用额外的反引号进行转义 |作为可选的 "sandbox" 对象选项属性提供的任何附加变量,也可用于(基于括号的)求值。
XPath 用户可能混淆的潜在来源
- 在 JSONPath 中,过滤器表达式除了其
@引用其子节点外,实际上还会选择直接子节点;而在 XPath 中,过滤条件不会选择子节点,而是界定结果中将获取其父节点中的哪些节点。 - 在 JSONPath 中,数组索引与 JavaScript 一样是从 0 开始的(从 0 开始),而在 XPath 中则是从 1 开始的。
- 在 JSONPath 中,相等性测试(按照 JavaScript)使用多个等号,而在 XPath 中则使用单个等号。
命令行界面
提供了一个基本的命令行界面(CLI)。使用 npx jsonpath-plus <json-file> <jsonpath-query> 访问它。
想法
- 支持过滤器之外的 OR(如 XPath 中的
|)以及分组。 - 创建一种语法,使其像 XPath 过滤器那样不选择子节点?
- 允许为 parentNode 等价物提供选项(保留直至根节点的 parent 和 parentProperty 对象的完整链)
开发
在 Node 上运行测试:```shell npm test
对于浏览器内测试:
- 提供 js/html 文件:```shell
npm run browser-test
安全
请参阅 SECURITY.md 了解重要的安全注意事项以及如何报告漏洞。