#json #streaming-json #json-parser #json-api

struson

一个低级别的流式JSON读取器和写入器

6个版本 (破坏性)

0.5.0 2024年3月17日
0.4.1 2024年1月30日
0.3.0 2023年9月5日
0.2.0 2023年8月6日
0.1.0 2023年4月22日

#142 in 解析器实现

Download history 810/week @ 2024-04-03 538/week @ 2024-04-10 539/week @ 2024-04-17 446/week @ 2024-04-24 393/week @ 2024-05-01 526/week @ 2024-05-08 348/week @ 2024-05-15 491/week @ 2024-05-22 444/week @ 2024-05-29 403/week @ 2024-06-05 419/week @ 2024-06-12 382/week @ 2024-06-19 629/week @ 2024-06-26 486/week @ 2024-07-03 540/week @ 2024-07-10 391/week @ 2024-07-17

2,144 每月下载量
用于 2 crates

MIT/Apache

765KB
12K SLoC

Struson
crates.io docs.rs

Struson是一个符合RFC 8259的流式JSON读取器和写入器。

其主要目的是允许以内存高效的方式写入JSON文档,而无需在内存中存储完整的JSON文档结构。

Struson的API受到了Java库Gson(类JsonReaderJsonWriter)的流式API的启发。它是相对底层的,其方法对应于JSON文档的元素,在其之上几乎没有抽象,允许读取和写入任何有效的JSON文档,无论其结构或内容如何。

注意:此库仍然是实验性的。性能还不是很好,API可能会在未来版本中更改;版本 < 1.0.0 可能不会遵循语义版本化,可能会发生破坏性更改。
欢迎反馈和改进建议!

为什么?

最流行的JSON Rust crates Serde JSON (serde_json)json-rust (json)主要提供用于处理JSON的高级API。

  • Serde JSON提供了一个API,用于将JSON转换为类似DOM的结构(模块serde_json::value)以及通过将结构体转换为JSON和反之亦然的对象映射功能。两者都需要在内存中存在完整的价值。特例serde_json::ser::Formatter实际上允许以流式方式写入JSON,但其API可以说是过于底层且不便于使用:您必须自己处理字符串转义,并且必须为每个方法调用提供写入器作为参数。
    然而,请注意,Serde JSON的StreamDeserializer允许以流式方式读取多个顶层值,并且可以通过自定义Visitor实现来解决某些流式使用案例,请参阅流式化数组丢弃数据的文档中的示例。

  • json-rust 提供了一个将 JSON 转换为类似 DOM 结构的 API(枚举 json::JsonValue),这需要完整的值存在于内存中。特质 json::codegen::Generator 提供了一个部分 API,用于以流式方式写入 JSON,但它缺少以流式方式写入 JSON 数组和对象的函数。

如果您需要以类似 DOM 的方式处理 JSON,或者需要对象映射功能将结构体转换为 JSON 及其反向转换,那么 Struson 不适合您的用例,您应该使用上述库之一。

主要功能

使用示例

提供了 API 的两种变体

  • 简单:确保在编译时正确使用 API
  • 高级:仅在运行时(通过引发恐慌)确保正确使用 API;更灵活且提供更多功能

简单 API

🔬 实验
简单 API 及其命名目前处于实验阶段,请在此处提供反馈 here。它必须通过在 Cargo.toml 中指定 experimental 功能来启用

[dependencies]
struson = { version = "...", features = ["experimental"] }

任何反馈都受欢迎!

读取

请参阅 SimpleJsonReader

use struson::reader::simple::*;

// In this example JSON data comes from a string;
// normally it would come from a file or a network connection
let json_reader = SimpleJsonReader::new(r#"["a", "short", "example"]"#.as_bytes());
let mut words = Vec::<String>::new();
json_reader.read_array_items(|item_reader| {
    let word = item_reader.read_string()?;
    words.push(word);
    Ok(())
})?;
assert_eq!(words, vec!["a", "short", "example"]);

对于读取嵌套值,可以使用方法 read_seekedread_seeked_multi

use struson::reader::simple::*;
use struson::reader::simple::multi_json_path::multi_json_path;

// In this example JSON data comes from a string;
// normally it would come from a file or a network connection
let json = r#"{
    "users": [
        {"name": "John", "age": 32},
        {"name": "Jane", "age": 41}
    ]
}"#;
let json_reader = SimpleJsonReader::new(json.as_bytes());

let mut ages = Vec::<u32>::new();
// Select the ages of all users
let json_path = multi_json_path!["users", [*], "age"];
json_reader.read_seeked_multi(&json_path, false, |value_reader| {
    let age = value_reader.read_number()??;
    ages.push(age);
    Ok(())
})?;
assert_eq!(ages, vec![32, 41]);

写入

请参阅 SimpleJsonWriter

use struson::writer::simple::*;

// In this example JSON bytes are stored in a Vec;
// normally they would be written to a file or network connection
let mut writer = Vec::<u8>::new();
let json_writer = SimpleJsonWriter::new(&mut writer);
json_writer.write_object(|object_writer| {
    object_writer.write_number_member("a", 1)?;
    object_writer.write_bool_member("b", true)?;
    Ok(())
})?;

let json = String::from_utf8(writer)?;
assert_eq!(json, r#"{"a":1,"b":true}"#);

高级 API

读取

请参阅 JsonStreamReader

use struson::reader::*;

// In this example JSON data comes from a string;
// normally it would come from a file or a network connection
let json = r#"{"a": [1, true]}"#;
let mut json_reader = JsonStreamReader::new(json.as_bytes());

json_reader.begin_object()?;
assert_eq!(json_reader.next_name()?, "a");

json_reader.begin_array()?;
assert_eq!(json_reader.next_number::<u32>()??, 1);
assert_eq!(json_reader.next_bool()?, true);
json_reader.end_array()?;

json_reader.end_object()?;
// Ensures that there is no trailing data
json_reader.consume_trailing_whitespace()?;

写入

请参阅 JsonStreamWriter

use struson::writer::*;

// In this example JSON bytes are stored in a Vec;
// normally they would be written to a file or network connection
let mut writer = Vec::<u8>::new();
let mut json_writer = JsonStreamWriter::new(&mut writer);

json_writer.begin_object()?;
json_writer.name("a")?;

json_writer.begin_array()?;
json_writer.number_value(1)?;
json_writer.bool_value(true)?;
json_writer.end_array()?;

json_writer.end_object()?;
// Ensures that the JSON document is complete and flushes the buffer
json_writer.finish_document()?;

let json = String::from_utf8(writer)?;
assert_eq!(json, r#"{"a":[1,true]}"#);

Serde 集成

可选与Serde集成,允许将Serialize写入到JsonWriter,并从JsonReader读取Deserialize。有关更多信息,请参阅此crate的serde模块链接

变更日志

请参阅GitHub发行版

构建

此项目使用cargo-make进行构建

cargo make

如果您不想安装cargo-make,可以手动运行Makefile.toml中声明的任务。

类似项目

许可协议

在以下任一许可协议下发布:

由您选择。

您为此项目做出的所有贡献都隐式地受到上述两种许可协议的许可,无需任何附加条款或条件。

注意:此双重许可与大多数Rust项目相同,请参阅Rust API指南

依赖关系

~0.3–0.9MB
~20K SLoC