Rust 标准库本身并没有直接支持 JSON 序列化的功能,但 Rust 社区提供了非常强大的第三方库来处理 JSON 数据,其中最流行和广泛使用的库是 Serde 和 Serde_json。
- Serde 是一个通用的序列化和反序列化框架,支持多种数据格式,包括 JSON、YAML、TOML 等。
- Serde_json 是 Serde 的一个分支,专门用于处理 JSON 数据。
现通过一个完整的例子,演示 serde
和 serde_json
的基本用法。
1. 创建项目
bash
cargo new serde_example --bin && cd serde_example
2. 添加依赖
在 Cargo.toml
中添加 serde
和 serde_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)]
- 作用:自动为结构体生成序列化和反序列化代码。
- 要求:所有字段类型必须也实现
Serialize
和Deserialize
(如String
、Vec<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. 常见场景
-
从文件读取配置:
rustlet file = File::open("config.json")?; let config: Config = serde_json::from_reader(file)?;
-
处理网络请求:
rustlet response = reqwest::get("https://api.example.com/data").await?; let data: Vec<Item> = response.json().await?; // reqwest 内置 serde 支持
9.总结
serde
:提供序列化/反序列化的框架和 trait。serde_json
:serde
的 JSON 格式实现。- 核心流程:
- 用
#[derive(Serialize, Deserialize)]
标记结构体。 - 使用
to_string()
/to_string_pretty()
序列化对象。 - 使用
from_str()
/from_reader()
反序列化 JSON。
- 用