@ jsonpath (英语) 
使用 JSONPath 表达式查询 JavaScript 对象 . 为Node.js提供强力/安全的JSONPath引擎.
查询示例
import { JSONPath } from '@astronautlabs/jsonpath';
let cities = [
{ name: "London", "population": 8615246 },
{ name: "Berlin", "population": 3517424 },
{ name: "Madrid", "population": 3165235 },
{ name: "Rome", "population": 2870528 }
];
let names = JSONPath.query(cities, '$..name');
// [ "London", "Berlin", "Madrid", "Rome" ]
安装
从 npm 安装 :
$ npm install @astronautlabs/jsonpath
JSONPath 语法
以下为语法和从 Stefan Goessner的原创文章 2007年引进了JSONPath.
| 乔森帕斯 | 说明 |
|---|---|
$ | 根对象/元素 |
@ | 当前对象/元素 |
. | 儿童成员经营者 |
.. | 递归后人运算符; JSONPath 从 E4X 借用此语法 |
* | 匹配所有对象/元素的通配符, 不论名称 |
[] | 下标运算符 |
[,] | 一组替代名称或数组索引的联盟运算符 |
[start:end:step] | 从 ES4 / Python 借入的分数片操作器 |
?() | 通过静态评价应用过滤器(script)表达式 |
() | 通过静态评价的脚本表达式 |
鉴于这一样本数据集,见以下示例:
{
"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
}
}
}
示例 JSONPath 表达式 :
| 乔森帕斯 | 说明 |
|---|---|
$.store.book[*].author | 店里所有书的作者 |
$..author | 所有作者 |
$.store.* | 所有的东西,一些书籍和一辆红色自行车 |
$.store..price | 店里所有东西的价格 |
$..book[2] | 第三本书 |
$..book[(@.length-1)] | 最后一本书通过脚本下标 |
$..book[-1:] | 最后一本书通过切片 |
$..book[0,1] | 前两本书通过下标工会 |
$..book[:2] | 前两本书通过下标数组切片 |
$..book[?(@.isbn)] | 过滤所有有 isbn 编号的书 |
$..book[?(@.price<10)] | 过滤所有比10便宜的书 |
$..book[?(@.price==8.95)] | 过滤所有花费8.95的书籍 |
$..book[?(@.price<30 && @.category=="fiction")] | 过滤所有便宜于30的虚构书籍 |
$..* | JSON结构的所有成员 |
方法
JSONPath.query (obj, pathExpression [, count]) (英语)
查找元素在 obj 匹配 pathExpression返回满足提供的 JSONPath 表达式的元素数组,如果没有匹配则返回空数组。 仅先返回 count 如果指定了元素.
let authors = jp.query(data, '$..author');
// [ 'Nigel Rees', 'Evelyn Waugh', 'Herman Melville', 'J. R. R. Tolkien' ]
JSONPath.paths (obj, path Expression [, 计数]) (中文(简体) )
查找元素的路径 obj 匹配 pathExpression返回满足提供的 JSONPath 表达式的一系列元素路径。 每个路径本身都是一组代表内部位置的密钥 obj 键。 仅先返回 count 如果指定了路径.
let paths = jp.paths(data, '$..author');
// [
// ['$', 'store', 'book', 0, 'author'] },
// ['$', 'store', 'book', 1, 'author'] },
// ['$', 'store', 'book', 2, 'author'] },
// ['$', 'store', 'book', 3, 'author'] }
// ]
JSONPath.nodes(obj,路径压缩[,计数])
查找元素及其相应的路径 obj 匹配 pathExpression。返回每个节点都有的节点对象数组 path 包含一组代表内部位置的密钥 obj,则a value 指向匹配的元素。 仅先返回 count 如果指定了节点.
let nodes = jp.nodes(data, '$..author');
// [
// { path: ['$', 'store', 'book', 0, 'author'], value: 'Nigel Rees' },
// { path: ['$', 'store', 'book', 1, 'author'], value: 'Evelyn Waugh' },
// { path: ['$', 'store', 'book', 2, 'author'], value: 'Herman Melville' },
// { path: ['$', 'store', 'book', 3, 'author'], value: 'J. R. R. Tolkien' }
// ]
JSONPath.value(obj, path Expression[, NewValue]) (英语)
返回第一个元素匹配的值 pathExpression如果 newValue ,设置第一个匹配元素的值并返回新值.
JSONPath.parent( Obj, 路径压缩)
返回第一个匹配元素的父元素.
JSONPath. apply(obj, pathExpression, fn) (英语)
运行所提供函数 fn ,并用函数的返回值来替换每个匹配元素。 该函数接受匹配元素的值作为其唯一的参数. 返回匹配其更新值的节点.
let nodes = jp.apply(data, '$..author', function(value) { return value.toUpperCase() });
// [
// { path: ['$', 'store', 'book', 0, 'author'], value: 'NIGEL REES' },
// { path: ['$', 'store', 'book', 1, 'author'], value: 'EVELYN WAUGH' },
// { path: ['$', 'store', 'book', 2, 'author'], value: 'HERMAN MELVILLE' },
// { path: ['$', 'store', 'book', 3, 'author'], value: 'J. R. R. TOLKIEN' }
// ]
JSONPath.parse( 路径压缩)
将提供的 JSONPath 表达式分析为路径组件及其相关操作.
let path = jp.parse('$..author');
// [
// { expression: { type: 'root', value: '$' } },
// { expression: { type: 'identifier', value: 'author' }, operation: 'member', scope: 'descendant' }
// ]
JSONPath.stringify( 路径)
以字符串形式返回路径表达式,给定路径。 提供的路径可能是一组平整的密钥, 由 : jp.nodes 例如,或可能是一种完全解析的路径表达式,形式为返回的路径组件数组 jp.parse。 。 。 .
let pathExpression = jp.stringify(['$', 'store', 'book', 0, 'author']);
// "$.store.book[0].author"
与原实施的差异
这一实施旨在与Stefan Goessner的最初实施相兼容,但有以下几个显著的例外.
评估脚本表达式
脚本表达式(即:, (...) 财务报告和审定财务报表 ?(...)静态评价 静态- eval 而不是直接使用基础脚本引擎. 这意味着,范围仅限于实例变量(例如:@),并且只有简单的表达式(没有副作用)才有效. 比如说, ?(@.length>10) 匹配超过10个元素的阵列,但是 ?(process.exit()) 将不进行评估,因为 process 将产生 ReferenceError。这种方法比 vm.runInNewContext,因为脚本引擎本身比较有限,并且与运行应用程序代码的引擎完全不同. 详见 执行 由评价员主持.
语法
这个项目使用正式的BNF 语法 来解析 JSONPath 表达式,这是一次逆向工程的尝试,它通过一系列的创造性正则表达式来解析原始执行的意图. 最初的regex方法有时可以原谅好坏(例如, $['store] => $['store']),在其他情况下,可能只是纯粹的错误(例如:. [ => $) (中文(简体) ).
其他细微差异
由于使用真实的解析器和静态评价,原始库中有一些可论证的bug没有通过这里:
- 下标中的字符串现在可能双引号
- 最终
step切片运算符中的参数现在可能是负数 - 脚本表达式现在可能包含
.财务报告和审定财务报表@不提及实例变量的字符 - 下标不再作为字符片处理字符串元素
- 非ascii 非单词字符在成员标识符名称中是无效的;取而代之的是被引用的下标字符串(例如,
$['$']改为$.$(中文(简体) ) - 现在,工会产生真正的工会,没有重复,没有巩固的结果