#serde-json #json #serde #serialization #v8

开发 serde_json_v8

与 V8 格式兼容的 JSON 序列化文件格式

3 个不稳定版本

使用旧的 Rust 2015

0.1.1 2021 年 5 月 5 日
0.1.0 2021 年 5 月 3 日
0.0.1 2019 年 4 月 22 日

#1669编码

每月 22 次下载
7 crates 中使用

MIT/Apache

25KB
264

Serde JSON V8

[dependencies]
serde_json_v8 = "0.1.0"

lib.rs:

Serde JSON V8

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 用于解析任何 io::Read,例如文件或 TCP 流。

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字符串。所以上面的代码输出看起来像 请在号码 "+44 1234567" 上调用 "John Doe"。引号出现是因为 v["name"] 是一个 &Value,包含一个JSON字符串,其JSON表示为 "John Doe"。以纯文本字符串打印,不带引号,涉及将JSON字符串转换为Rust字符串,使用 as_str() 或避免在下一节中描述的方式使用 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,并在布局不符合预期的 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

构建 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 值时插入。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)] 注解的结构体或枚举。

无标准库支持

此软件包目前需要 Rust 标准库。有关在无标准库的情况下使用 Serde 的 JSON 支持,请参阅 serde-json-core 软件包。

依赖项

~0.5–1.1MB
~23K SLoC