#serde-json #deserialize-json #io-read #json-parser #json-text #data #string

急切json

通过缓冲到字符串来从 io::Read 解析 JSON

1 个不稳定版本

使用旧的 Rust 2015

0.1.0 2018年2月15日

#2000 in 编码

MIT/Apache

340KB
8K SLoC

Serde JSON — 构建状态 最新版本 Rustc 版本 1.36+

Serde 是一个用于高效且通用地序列化和反序列化 Rust 数据结构的框架。


[dependencies]
serde_json = "1.0"

你可能还在找

JSON 是一种广泛使用的开放标准格式,它使用可读文本来传输由键值对组成的数据对象。

{
    "name": "John Doe",
    "age": 43,
    "address": {
        "street": "10 Downing Street",
        "city": "London"
    },
    "phones": [
        "+44 1234567",
        "+44 2345678"
    ]
}

在 Rust 中处理 JSON 数据可能有三种常见方式。

  • 作为文本数据。 你在 HTTP 端点收到的未经处理的 JSON 数据字符串,从文件中读取,或准备发送到远程服务器。
  • 作为无类型或松散类型的表示。 你可能想要在传递之前检查某些 JSON 数据是否有效,但不知道它包含的结构。或者你想要执行非常基本的操作,如在一个特定的位置插入一个键。
  • 作为强类型 Rust 数据结构。 当你期望所有或大部分数据都符合特定结构,并希望在不受 JSON 松散性质的影响下完成实际工作。

Serde JSON 提供了在每种表示之间转换数据的高效、灵活、安全的方法。

操作无类型 JSON 值

任何有效的 JSON 数据都可以以下递归枚举表示形式进行操作。此数据结构是 serde_json::Value

enum Value {
    Null,
    Bool(bool),
    Number(Number),
    String(String),
    Array(Vec<Value>),
    Object(Map<String, Value>),
}

可以使用`serde_json::from_str`函数将JSON数据解析为serde_json::Value类型。此外,还有`from_slice`函数用于从字节数组&[u8]中解析,以及`from_reader`函数用于从文件或TCP流等任何io::Read中解析。

use serde_json::{Result, Value};

fn untyped_example() -> Result<()> {
    // Some JSON input data as a &str. Maybe this comes from the user.
    let data = r#"
        {
            "name": "John Doe",
            "age": 43,
            "phones": [
                "+44 1234567",
                "+44 2345678"
            ]
        }"#;

    // Parse the string of data into serde_json::Value.
    let v: Value = serde_json::from_str(data)?;

    // Access parts of the data by indexing with square brackets.
    println!("Please call {} at the number {}", v["name"], v["phones"][0]);

    Ok(())
}

v["name"]这样的方括号索引操作返回的是该索引处的数据的引用,因此其类型是&Value。JSON映射可以使用字符串键进行索引,而JSON数组可以使用整数键进行索引。如果数据类型不适合索引的类型,或者映射中不包含要索引的键,或者向向量中索引的索引超出范围,则返回的元素是Value::Null

打印Value时,它会被打印为JSON字符串。因此,在上述代码中,输出看起来像Please call "John Doe" at the number "+44 1234567"。引号出现是因为v["name"]是一个包含JSON字符串的&Value,其JSON表示形式为"John Doe"。如果不带引号以纯文本形式打印,则需要使用`as_str`方法或将Rust字符串从JSON字符串转换,或者避免在下一节中描述的使用Value

Value表示适用于非常基础的任务,但对于更重要的任务来说可能会很繁琐。错误处理实现起来很冗长,例如,想象一下试图检测输入数据中是否存在未识别的字段。当你犯错时,编译器无法提供帮助,例如,想象一下在一个使用几十处的地方将v["name"]作为v["nmae"]的拼写错误。

将JSON解析为强类型数据结构

Serde提供了一种强大的方法,可以将JSON数据自动映射到Rust数据结构中。

use serde::{Deserialize, Serialize};
use serde_json::Result;

#[derive(Serialize, Deserialize)]
struct Person {
    name: String,
    age: u8,
    phones: Vec<String>,
}

fn typed_example() -> Result<()> {
    // Some JSON input data as a &str. Maybe this comes from the user.
    let data = r#"
        {
            "name": "John Doe",
            "age": 43,
            "phones": [
                "+44 1234567",
                "+44 2345678"
            ]
        }"#;

    // Parse the string of data into a Person object. This is exactly the
    // same function as the one that produced serde_json::Value above, but
    // now we are asking it for a Person as output.
    let p: Person = serde_json::from_str(data)?;

    // Do things just like with any other Rust data structure.
    println!("Please call {} at the number {}", p.name, p.phones[0]);

    Ok(())
}

这是与之前相同的 serde_json::from_str 函数,但这次我们将返回值赋给一个类型为 Person 的变量,这样 Serde 将自动将输入数据解释为 Person,并在布局不符合预期时产生有信息的错误信息。

任何实现了 Serde 的 Deserialize 特质的类型都可以这样反序列化。这包括内置的 Rust 标准库类型,如 Vec<T>HashMap<K, V>,以及任何使用 #[derive(Deserialize)] 注解的结构体或枚举。

一旦我们有 p 类型为 Person,我们的 IDE 和 Rust 编译器就可以像处理任何其他 Rust 代码一样帮助我们正确使用它。IDE 可以自动补全字段名以防止输入错误,这在 serde_json::Value 表示法中是不可能的。Rust 编译器可以检查当我们写入 p.phones[0] 时,则 p.phones 保证是一个 Vec<String>,所以对其索引是有意义的并产生一个 String

使用 Serde derive 宏的必要设置在 Serde 网站的 Using derive 页面上有解释。

构建 JSON 值

Serde JSON 提供了一个 json!,以非常自然的 JSON 语法构建 serde_json::Value 对象。

use serde_json::json;

fn main() {
    // The type of `john` is `serde_json::Value`
    let john = json!({
        "name": "John Doe",
        "age": 43,
        "phones": [
            "+44 1234567",
            "+44 2345678"
        ]
    });

    println!("first phone number: {}", john["phones"][0]);

    // Convert to a string of JSON and print it out
    println!("{}", john.to_string());
}

Value::to_string() 函数将一个 serde_json::Value 转换为一个 JSON 文本的 String

json! 宏的一个巧妙之处在于,可以在构建 JSON 值时直接将变量和表达式插入到 JSON 值中。Serde 将在编译时检查您正在插入的值是否可以表示为 JSON。

let full_name = "John Doe";
let age_last_year = 42;

// The type of `john` is `serde_json::Value`
let john = json!({
    "name": full_name,
    "age": age_last_year + 1,
    "phones": [
        format!("+44 {}", random_phone())
    ]
});

这非常方便,但我们遇到了之前与 Value 相关的问题:如果出错,IDE 和 Rust 编译器无法提供帮助。Serde JSON 提供了一种将强类型数据结构序列化为 JSON 文本的好方法。

通过序列化数据结构创建 JSON

数据结构可以通过serde_json::to_string转换为JSON字符串。还有serde_json::to_vec,它将序列化为Vec<u8>,以及serde_json::to_writer,它将序列化为任何io::Write,如文件或TCP流。

use serde::{Deserialize, Serialize};
use serde_json::Result;

#[derive(Serialize, Deserialize)]
struct Address {
    street: String,
    city: String,
}

fn print_an_address() -> Result<()> {
    // Some data structure.
    let address = Address {
        street: "10 Downing Street".to_owned(),
        city: "London".to_owned(),
    };

    // Serialize it to a JSON string.
    let j = serde_json::to_string(&address)?;

    // Print, write to a file, or send to an HTTP server.
    println!("{}", j);

    Ok(())
}

任何实现了Serde的Serialize特质的类型都可以用这种方式序列化。这包括内置的Rust标准库类型,如Vec<T>HashMap<K, V>,以及任何带有#[derive(Serialize)]注解的结构体或枚举。

性能

它很快。您应该期望每秒500到1000兆字节的反序列化速度和每秒600到900兆字节的序列化速度,具体取决于您的数据特性。这与其他最快的C和C++ JSON库具有竞争力,甚至在许多情况下快30%。基准测试在serde-rs/json-benchmark仓库中。

寻求帮助

Serde是Rust中使用最广泛的库之一,因此任何Rustaceans聚集的地方都能帮助你。对于聊天,考虑尝试非官方社区Discord的#rust-questions#rust-beginners频道(邀请:https://discord.gg/rust-lang-community),官方Rust项目Discord的#rust-usage#beginners频道(邀请:https://discord.gg/rust-lang),或Zulip的#general流。对于异步,可以考虑StackOverflow上的[rust]标签、/r/rust subreddits(每周有固定的简单问题帖子)或Rust Discourse论坛。在仓库中提交支持问题是可以接受的,但它们通常不会像上述任何一种那样得到许多关注,并且可能在一段时间后没有回应而被关闭。

无标准支持

只要有内存分配器,就可以在不使用Rust标准库的其余部分的情况下使用serde_json。禁用默认的"std"功能并启用"alloc"功能。

[dependencies]
serde_json = { version = "1.0", default-features = false, features = ["alloc"] }

有关Serde在无内存分配器的情况下支持JSON的详细信息,请参阅serde-json-corecrate。


许可证

根据您的选择,在Apache License, Version 2.0MIT license下获得许可。
除非您明确说明,否则根据Apache-2.0许可证定义的,您有意提交以包含在此crate中的任何贡献,将如上所述双许可,没有额外的条款或条件。

依赖项

~265–670KB
~13K SLoC