Rust 标准库本身并没有直接支持 JSON 序列化的功能,但 Rust 社区提供了非常强大的第三方库来处理 JSON 数据,其中最流行和广泛使用的库是 Serde 和 Serde_json。

  • Serde 是一个通用的序列化和反序列化框架,支持多种数据格式,包括 JSON、YAML、TOML 等。
  • Serde_json 是 Serde 的一个分支,专门用于处理 JSON 数据。

现通过一个完整的例子,演示 serdeserde_json 的基本用法。

1. 创建项目

bash 复制代码
cargo new serde_example --bin && cd serde_example

2. 添加依赖

Cargo.toml 中添加 serdeserde_json

toml 复制代码
[dependencies]
serde = { version = "1.0", features = ["derive"] }  # 启用 derive 宏
serde_json = "1.0"

3. 定义数据结构并实现序列化

src/main.rs 中编写代码:

rust 复制代码
use serde::{Serialize, Deserialize};

// 1. 定义可序列化的结构体
#[derive(Debug, Serialize, Deserialize)]
struct Person {
    name: String,
    age: u8,
    hobbies: Vec<String>,
    is_student: bool,
}

fn main() {
    // 2. 创建 Rust 对象
    let person = Person {
        name: "Alice".to_string(),
        age: 30,
        hobbies: vec!["Reading".to_string(), "Coding".to_string()],
        is_student: false,
    };

    // 3. 序列化为 JSON 字符串
    let json_string = serde_json::to_string(&person).unwrap();
    println!("序列化后的 JSON: {}", json_string);
    // 输出: {"name":"Alice","age":30,"hobbies":["Reading","Coding"],"is_student":false}

    // 4. 序列化为格式化的 JSON(带缩进)
    let pretty_json = serde_json::to_string_pretty(&person).unwrap();
    println!("格式化后的 JSON:\n{}", pretty_json);
    // 输出:
    // {
    //   "name": "Alice",
    //   "age": 30,
    //   "hobbies": ["Reading", "Coding"],
    //   "is_student": false
    // }

    // 5. 从 JSON 字符串反序列化为 Rust 对象
    let json_str = r#"{"name":"Bob","age":25,"hobbies":["Gaming"],"is_student":true}"#;
    let deserialized_person: Person = serde_json::from_str(json_str).unwrap();
    println!("反序列化后的对象: {:?}", deserialized_person);
    // 输出: Person { name: "Bob", age: 25, hobbies: ["Gaming"], is_student: true }
}

4. 运行程序

bash 复制代码
cargo run

5. 关键概念解释

5.1 #[derive(Serialize, Deserialize)]

  • 作用:自动为结构体生成序列化和反序列化代码。
  • 要求:所有字段类型必须也实现 SerializeDeserialize(如 StringVec<T>)。

5.2 序列化函数

  • serde_json::to_string(&obj):将对象转为紧凑的 JSON 字符串。
  • serde_json::to_string_pretty(&obj):转为带缩进的 JSON 字符串(适合打印/存储)。

5.3 反序列化函数

  • serde_json::from_str(json_str):从字符串解析 JSON。
  • serde_json::from_reader(reader):从文件或网络流解析 JSON(更高效)。

5.4 类型注解

反序列化时必须指定目标类型(如 Person),Rust 通过类型推断确定如何解析 JSON:

rust 复制代码
let person: Person = serde_json::from_str(json_str)?;

6. 进阶用法:处理可选字段和自定义名称

rust 复制代码
#[derive(Debug, Serialize, Deserialize)]
struct Config {
    #[serde(rename = "server_addr")]  // 指定 JSON 中的字段名
    address: String,
    port: u16,
    timeout: Option<u32>,  // 可选字段,对应 JSON 中可能不存在的字段
}

fn main() {
    let json = r#"{"server_addr":"localhost","port":8080}"#;
    let config: Config = serde_json::from_str(json).unwrap();
    println!("配置: {:?}", config);
    // 输出: Config { address: "localhost", port: 8080, timeout: None }
}

7. 错误处理

序列化/反序列化可能失败(如 JSON 格式错误),需处理错误:

rust 复制代码
let json = r#"{"name":"Alice","age":"thirty"}"#;  // 错误:age 应为数字
let result: Result<Person, serde_json::Error> = serde_json::from_str(json);

match result {
    Ok(person) => println!("解析成功: {:?}", person),
    Err(e) => println!("解析失败: {}", e),  // 输出类型不匹配错误
}

8. 常见场景

  1. 从文件读取配置

    rust 复制代码
    let file = File::open("config.json")?;
    let config: Config = serde_json::from_reader(file)?;
  2. 处理网络请求

    rust 复制代码
    let response = reqwest::get("https://api.example.com/data").await?;
    let data: Vec<Item> = response.json().await?;  // reqwest 内置 serde 支持

9.总结

  • serde:提供序列化/反序列化的框架和 trait。
  • serde_jsonserde 的 JSON 格式实现。
  • 核心流程
    1. #[derive(Serialize, Deserialize)] 标记结构体。
    2. 使用 to_string()/to_string_pretty() 序列化对象。
    3. 使用 from_str()/from_reader() 反序列化 JSON。