5个版本

0.8.4-delete-path-fix2024年2月27日
0.8.3-add-traits2024年2月20日
0.8.2-delete-path2024年1月2日
0.8.1-with-set-rename2023年10月21日
0.8.1-delete-path2024年1月2日

#766 in 解析器实现

每月24次下载
用于 streamdal-wasm-transform

MIT 许可证

3MB
3.5K SLoC

GJSON
GJSON Playground

<警告>

这是一个由 gjson.rs 库的官方版本所 fork 出来的库,该库被 streamdal/wasm 组件使用。这个版本的库允许你以非优化方式设置 JSON 值。

添加的新功能包括

  • set_overwrite()
  • delete_path()

此外,还添加了以下特质

  • struct Value: DebugClone
  • enum Kind: Debug

注意:由于此 fork 的发布频率不高,该仓库没有自动发布 - 你需要手动执行发布过程

  1. 修改代码
  2. 运行测试
  3. 确定新版本 - 你应该 尝试 保持与上游相同的版本,并仅添加标签。 但你不可以为同一版本发布多个标签
  4. 使用新版本更新 Cargo.toml 中的版本
  5. git提交 -a
  6. gittag 0.8.1-my-new-label
  7. gitpush origin 0.8.1-my-new-label
  8. cargo发布 --token <token>

</警告>

快速获取JSON值

GJSON 是一个 Rust crate,它提供了一种快速且 简单 的方式来从 JSON 文档中获取值。它具有如下功能:单行检索点符号路径迭代解析 JSON 行

此库使用与 Go 版本 相同的路径语法。

入门

使用方法

将以下内容添加到您的 Cargo.toml 文件中

[dependencies]
gjson = "0.8"

获取值

通过指定的路径搜索 json。路径使用点语法,例如 "name.last" 或 "age"。找到值后立即返回。

const JSON: &str = r#"{"name":{"first":"Janet","last":"Prichard"},"age":47}"#;

fn main() {
    let value = gjson::get(JSON, "name.last");
    println!("{}", value);
}

这将打印

Prichard

路径语法

以下是路径语法的简要概述,更完整的信息请参阅 GJSON 语法

路径是由点分隔的一系列键。键可以包含特殊通配符 '*' 和 '?'。要访问数组值,请使用索引作为键。要获取数组中的元素数量或访问子路径,请使用 '#' 字符。点和通配符可以用反斜杠 '\\' 转义。

{
  "name": {"first": "Tom", "last": "Anderson"},
  "age":37,
  "children": ["Sara","Alex","Jack"],
  "fav.movie": "Deer Hunter",
  "friends": [
    {"first": "Dale", "last": "Murphy", "age": 44, "nets": ["ig", "fb", "tw"]},
    {"first": "Roger", "last": "Craig", "age": 68, "nets": ["fb", "tw"]},
    {"first": "Jane", "last": "Murphy", "age": 47, "nets": ["ig", "tw"]}
  ]
}
"name.last"          >> "Anderson"
"age"                >> 37
"children"           >> ["Sara","Alex","Jack"]
"children.#"         >> 3
"children.1"         >> "Alex"
"child*.2"           >> "Jack"
"c?ildren.0"         >> "Sara"
"fav\.movie"         >> "Deer Hunter"
"friends.#.first"    >> ["Dale","Roger","Jane"]
"friends.1.last"     >> "Craig"

您还可以使用 #(...) 来查询数组中的第一个匹配项,或使用 #(...)# 来找到所有匹配项。查询支持 ==!=<<=>>= 比较运算符以及简单的模式匹配运算符 %(类似)和 !%(不类似)。

friends.#(last=="Murphy").first    >> "Dale"
friends.#(last=="Murphy")#.first   >> ["Dale","Jane"]
friends.#(age>45)#.last            >> ["Craig","Murphy"]
friends.#(first%"D*").last         >> "Murphy"
friends.#(first!%"D*").last        >> "Craig"
friends.#(nets.#(=="fb"))#.first   >> ["Dale","Roger"]

值类型

将 JSON 值转换为 Rust 类型

value.i8()
value.i16()
value.i32()
value.i64()
value.u8()
value.u16()
value.u32()
value.u64()
value.f32()
value.f64()
value.bool()
value.str()    // a string representation
value.json()   // the raw json

在值上工作的便捷函数

value.kind()             // String, Number, True, False, Null, Array, or Object
value.exists()           // returns true if value exists in JSON.
value.get(path: &str)    // get a child value
value.each(|key, value|) // iterate over child values

64 位整数

调用 value.i64()value.u64() 可以读取所有 64 位,允许处理大整数。

value.i64() -> i64   // -9223372036854775808 to 9223372036854775807
value.u64() -> u64   // 0 to 18446744073709551615

修饰符和路径链接

修饰符是执行自定义处理的一个路径组件。

可以使用管道字符将多个路径 "链接" 在一起。这对于从修改后的查询中获取值很有用。

例如,在上述 JSON 文档中使用内置的 @reverse 修饰符,我们将获取 children 数组并反转其顺序

"children|@reverse"           >> ["Jack","Alex","Sara"]
"children|@reverse|0"         >> "Jack"

目前有以下内置修饰符

  • @reverse:反转数组或对象的成员。
  • @ugly:从 JSON 文档中删除所有空白。
  • @pretty:使 JSON 文档更易于阅读。
  • @this:返回当前元素。它可以用来检索根元素。
  • @valid:确保 JSON 文档是有效的。
  • @flatten:展平数组。
  • @join:将多个对象合并成一个对象。

修饰符参数

修饰符可能接受一个可选参数。参数可以是有效的 JSON 文档或只是字符。

例如,@pretty 修饰符接受一个 JSON 对象作为参数。

@pretty:{"sortKeys":true} 

这使得 JSON 更美观并按顺序排列所有键。

{
  "age":37,
  "children": ["Sara","Alex","Jack"],
  "fav.movie": "Deer Hunter",
  "friends": [
    {"age": 44, "first": "Dale", "last": "Murphy"},
    {"age": 68, "first": "Roger", "last": "Craig"},
    {"age": 47, "first": "Jane", "last": "Murphy"}
  ],
  "name": {"first": "Tom", "last": "Anderson"}
}

@pretty 的完整选项列表是 sortKeysindentprefixwidth。有关更多信息,请参阅 美观选项

JSON 行

支持使用 .. 前缀的 JSON Lines,它将多行文档视为一个数组。

例如:

{"name": "Gilbert", "age": 61}
{"name": "Alexa", "age": 34}
{"name": "May", "age": 57}
{"name": "Deloise", "age": 44}
..#                   >> 4
..1                   >> {"name": "Alexa", "age": 34}
..3                   >> {"name": "Deloise", "age": 44}
..#.name              >> ["Gilbert","Alexa","May","Deloise"]
..#(name="May").age   >> 57

获取嵌套数组值

假设你想要从以下 JSON 中获取所有姓氏

{
  "programmers": [
    {
      "firstName": "Janet", 
      "lastName": "McLaughlin", 
    }, {
      "firstName": "Elliotte", 
      "lastName": "Hunter", 
    }, {
      "firstName": "Jason", 
      "lastName": "Harold", 
    }
  ]
}

你可以使用路径 "programmers.#.lastName" 如此使用

value := gjson::get(json, "programmers.#.lastName");
for name in value.array() {
	println!("{}", name);
}

你还可以查询数组内的对象

let name = gjson::get(json, "programmers.#(lastName=Hunter).firstName");
println!("{}", name)  // prints "Elliotte"

遍历对象或数组

ForEach 函数允许快速遍历对象或数组。对于对象,键和值会被传递给迭代函数。对于数组,只传递值。从迭代器函数返回 false 将停止迭代。

let value := gjson::get(json, "programmers")
value::each(|key, value| {
	println!("{}", value);
	true // keep iterating
});

简单解析和获取

有一个 gjson::parse(json) 函数可以进行简单解析,以及 value.get(path) 可以搜索值。

例如,以下都会返回相同的值

gjson::parse(json).get("name").get("last");
gjson::get(json, "name").get("last");
gjson::get(json, "name.last");

检查值是否存在

有时你只想知道一个值是否存在。

let value = gjson::get(json, "name.last");
if !value.exists() {
	println!("no last name");
} else {
	println!("{}", value);
}

// Or as one step
if gjson::get(json, "name.last").exists() {
	println!("has a last name");
}

验证 JSON

Get*Parse* 函数期望 JSON 是有效的。无效的 JSON 不会引发恐慌,但它可能返回意外的值。

如果你正在从不可预测的源消费 JSON,那么在使用 GJSON 之前验证可能是个好主意。

if !gjson::valid(json) {
	return Err("invalid json");
}
let value = gjson::get(json, "name.last");

依赖项