25个版本 (6个破坏性更新)
0.7.0 | 2024年7月24日 |
---|---|
0.6.0 | 2024年6月4日 |
0.5.0 | 2024年2月19日 |
0.3.5 | 2023年11月24日 |
0.1.1 | 2021年5月25日 |
#1785 in 数据结构
797,087 每月下载量
在 78 个crate(15个直接) 中使用
155KB
3.5K SLoC
jsonpath-rust
该库提供根据筛选查询查找数据集的基本功能。该想法来自XPath对XML结构的处理。详细信息可以在此处找到。因此,JsonPath是JSON的查询语言,类似于XPath对XML的处理。JsonPath查询是一组断言,用于指定需要验证的JSON字段。
Python绑定(jsonpath-rust-bindings)在pypi上可用
pip install jsonpath-rust-bindings
简单示例
假设我们有一个以下的json
{
"shop": {
"orders": [
{
"id": 1,
"active": true
},
{
"id": 2
},
{
"id": 3
},
{
"id": 4,
"active": true
}
]
}
}
并且我们追求找到所有具有字段'active'的订单id。我们可以构造如下的jsonpath实例 $.shop.orders[?(@.active)].id
并得到结果 [1,4]
jsonpath描述
函数
大小
函数 length()
将筛选表达式的输出转换为该元素的大小。它与数组一起工作,因此返回给定数组的大小,否则为null。
$.some_field.长度()
用于对象时,可以使用操作符 [*]
。代码示例:$.object.[*].length()
操作符
操作符 | 描述 | 使用位置 |
---|---|---|
$ |
指向json根的指针。 | 建议从根开始使用每个jsonpath。同时,在过滤器内指出路径是从根开始的。 |
@ |
指向过滤器操作中的当前元素。 | 用于在过滤器操作中迭代集合。 |
* 或 [*] |
通配符。将所有对象和元素(无论其名称如何)列入列表。 | 类似平坦映射操作。 |
<..> |
下降操作。将所有对象、该对象的子对象等列入列表。 | 类似平坦映射操作。 |
.<name> 或 .['<name>'] |
指向对象字段的键 | 用于获取特定字段。 |
['<name>' (, '<name>')] |
键列表 | 与单个键的用法相同,但用于列表。 |
[<number>] |
通过索引获取元素的过滤器。 | |
[<number> (, <number>)] |
根据这些数字的索引表示的数组元素列表。 | |
[<start>:<end>:<step>] |
切片操作符通过使用索引来获取元素列表。默认步长 = 1,开始 = 0,结束 = 数组长度。元素可以省略 [:] |
|
[?(<表达式>)] |
用于过滤列表中的元素的逻辑表达式。 | 通常与数组预先使用。 |
过滤器表达式
过滤器操作符中出现的表达式如下 [?(@.len > 0)]
。一般表达式由以下元素组成
- 左操作数和右操作数,即可以是一个静态值,表示为原始类型,如数字、字符串值
'value'
,它们的数组或另一个json路径实例。 - 表达式符号,表示可以执行什么操作
表达式符号 | 描述 | 使用位置 |
---|---|---|
! |
Not | 用于否定表达式 |
== |
Equal | 用于比较数字或字符串文字 |
!= |
Unequal | 以与等于相反的方式比较数字或字符串文字 |
< |
Less | 用于比较数字 |
> |
Greater | 用于比较数字 |
<= |
Less or equal | 用于比较数字 |
>= |
Greater or equal | 用于比较数字 |
~= |
Regular expression | 在左侧找到右侧的输入 |
in |
在右侧元素的列表中找到左侧元素。 | |
nin |
与上述相同,但意义相反。 | |
size |
左侧数组的尺寸应与右侧的数字相对应。 | |
noneOf |
左侧与右侧没有交集 | |
anyOf |
左侧至少与右侧有一个交集 | |
subsetOf |
左侧是右侧的子集 | |
? |
存在操作符。 | 操作员检查左侧显示的字段是否存在,如下所示 [?(@.key.isActive)] |
可以使用 ||
和 &&
(逻辑或和逻辑与)连接筛选表达式,如下所示
{
"key": [
{
"city": "London",
"capital": true,
"size": "big"
},
{
"city": "Berlin",
"capital": true,
"size": "big"
},
{
"city": "Tokyo",
"capital": true,
"size": "big"
},
{
"city": "Moscow",
"capital": true,
"size": "big"
},
{
"city": "Athlon",
"capital": false,
"size": "small"
},
{
"city": "Dortmund",
"capital": false,
"size": "big"
},
{
"city": "Dublin",
"capital": true,
"size": "small"
}
]
}
路径 $.key[?(@.capital == false || @size == 'small')].city
将得到以下结果
[
"Athlon",
"Dublin",
"Dortmund"
]
而路径 $.key[?(@.capital == false && @size != 'small')].city
,反过来,将得到以下结果
[
"Dortmund"
]
默认情况下,运算符具有不同的优先级,因此 &&
的优先级更高,因此可以通过使用括号来改变它。 $.[?((@.f == 0 || @.f == 1) && ($.x == 15))].city
示例
给定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
}
},
"expensive": 10
}
JsonPath | 结果 |
---|---|
$.store.book[*].author |
所有书籍的作者 |
$..book[?(@.isbn)] |
所有带有ISBN号的书籍 |
$.store.* |
所有事物,包括书籍和自行车 |
$..author |
所有作者 |
$.store..price |
所有事物的价格 |
$..book[2] |
第三本书 |
$..book[-2] |
倒数第二本书 |
$..book[0,1] |
前两本书 |
$..book[:2] |
从索引0(包含)到索引2(不包含)的所有书籍 |
$..book[1:2] |
从索引1(包含)到索引2(不包含)的所有书籍 |
$..book[-2:] |
最后两本书 |
$..book[2:] |
从尾部开始的第二本书 |
$.store.book[?(@.price< 10)] |
价格低于10的所有书籍 |
$..book[?(@.price<= $.expensive)] |
商店中不是“expensive”的所有书籍 |
$..book[?(@.author~= '(?i)REES')] |
匹配正则表达式(忽略大小写)的所有书籍 |
$..* |
给我所有东西 |
图书馆使用
图书馆旨在提供使用上述语法查找数据切片的基本功能。依赖项如下所示: jsonpath-rust = *
基本示例如下
库返回一个 json path value
作为结果。这是一个枚举类型,代表
Slice
- 指向传入原始json的指针NewValue
- 在路径(例如长度运算符)中生成的新json数据NoValue
- 表示在大多数情况下,由于字段缺失或不一致的数据,给定的JSON与jsonpath之间没有匹配。
要提取数据,有两种方法,在 value
上提供。
let v:JsonPathValue<Value> =...
v.to_data();
v.slice_or(&some_dafault_value)
查找
有4个不同的函数可以在 value
内查找数据。它们都接受引用,以提高可重用性。与简单的查找相比,JSON解析和jsonpath解析可能需要更多的时间。
方法 find
、find_as_path
、find_slice
和 find_slice_ptr
接受相同的输入,但根据您的用例以不同的方式处理它们。它们在 文档 中有进一步说明。
use jsonpath_rust::{JsonPath, JsonPathValue};
use serde_json::json;
use std::str::FromStr;
fn main() {
let data = json!({"first":{"second":[{"active":1},{"passive":1}]}});
let path = JsonPath::from_str("$.first.second[?(@.active)]").unwrap();
let slice_of_data = path.find_slice(&data);
let expected_value = json!({"active":1});
let expected_path = "$.['first'].['second'][0]".to_string();
assert_eq!(
slice_of_data,
vec![JsonPathValue::Slice(&expected_value, expected_path)]
);
}
结构
JsonPath
的内部结构可以在这里找到:https://docs.rs/jsonpath-rust/latest/jsonpath_rust/parser/model/enum.JsonPath.html
JsonPathIndex
的内部结构可以在这里找到:https://docs.rs/jsonpath-rust/latest/jsonpath_rust/parser/model/enum.JsonPathIndex.html
如何贡献
待定
如何更新版本
- 更新文件
- 提交它们
- 添加标签
git tag -a v<Version> -m "message"
- git push origin <tag_name>
依赖
~4.5–6.5MB
~124K SLoC