#json-path #json #json-query #xpath #query-language

jsonpath-rust

该库提供根据筛选查询查找数据集的基本功能

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 数据结构

Download history 119978/week @ 2024-04-26 115479/week @ 2024-05-03 126806/week @ 2024-05-10 124596/week @ 2024-05-17 130509/week @ 2024-05-24 153695/week @ 2024-05-31 166168/week @ 2024-06-07 149147/week @ 2024-06-14 154806/week @ 2024-06-21 158503/week @ 2024-06-28 162012/week @ 2024-07-05 154564/week @ 2024-07-12 156573/week @ 2024-07-19 161854/week @ 2024-07-26 175254/week @ 2024-08-02 273188/week @ 2024-08-09

797,087 每月下载量
78 个crate(15个直接) 中使用

MIT 许可证

155KB
3.5K SLoC

jsonpath-rust

Crates.io docs.rs Rust CI

该库提供根据筛选查询查找数据集的基本功能。该想法来自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解析可能需要更多的时间。

方法 findfind_as_pathfind_slicefind_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