Rust语言从入门到精通系列 - Serde序列化/反序列化模块入门指北

3 分钟阅读

Serde 是一个用于序列化和反序列化 Rust 数据结构的库。它支持 JSON、BSON、YAML 等多种格式,并且可以自定义序列化和反序列化方式。Serde 的特点是代码简洁、易于使用、性能高效。它是 Rust 生态中最受欢迎的序列化库之一。

基础用法

安装

在 Rust 项目中使用 Serde,需要在Cargo.toml文件中添加如下依赖:

1
2
[dependencies]
serde = { version = "1.0", features = ["derive"] }

其中features = ["derive"]表示使用 Serde 的派生宏,可以自动生成序列化和反序列化代码。

序列化

使用 Serde 进行序列化,需要先将数据结构实现serde::Serialize trait。例如,我们定义一个Animal结构体,包含名称和年龄两个字段:

1
2
3
4
5
#[derive(Serialize)]
struct Animal {
    name: String,
    age: u32,
}

然后,我们可以使用serde_json库将Animal结构体序列化为 JSON 字符串:

1
2
3
4
5
6
7
8
use serde_json;

let animal = Animal {
    name: "Tom".to_owned(),
    age: 3,
};
let json = serde_json::to_string(&animal).unwrap();
println!("{}", json); // {"name":"Tom","age":3}

反序列化

使用 Serde 进行反序列化,需要先将数据结构实现serde::Deserialize trait。例如,我们定义一个Animal结构体,包含名称和年龄两个字段:

1
2
3
4
5
#[derive(Deserialize)]
struct Animal {
    name: String,
    age: u32,
}

然后,我们可以使用serde_json库将 JSON 字符串反序列化为Animal结构体:

1
2
3
4
5
use serde_json;

let json = r#"{"name":"Tom","age":3}"#;
let animal: Animal = serde_json::from_str(json).unwrap();
println!("{:?}", animal); // Animal { name: "Tom", age: 3 }

进阶用法

自定义序列化和反序列化

如果默认的序列化和反序列化方式无法满足需求,可以自定义序列化和反序列化方式。例如,我们定义一个Animal结构体,包含名称和年龄两个字段,但是希望在序列化时,将名称转换为大写字母,反序列化时,将名称转换为小写字母:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
use serde::{Serialize, Deserialize, Serializer, Deserializer};

#[derive(Serialize, Deserialize)]
struct Animal {
    #[serde(serialize_with = "serialize_name", deserialize_with = "deserialize_name")]
    name: String,
    age: u32,
}

fn serialize_name<S>(name: &String, serializer: S) -> Result<S::Ok, S::Error>
where
    S: Serializer,
{
    serializer.serialize_str(&name.to_uppercase())
}

fn deserialize_name<'de, D>(deserializer: D) -> Result<String, D::Error>
where
    D: Deserializer<'de>,
{
    let name = String::deserialize(deserializer)?;
    Ok(name.to_lowercase())
}

Animal结构体中,我们使用#[serde(serialize_with = "serialize_name", deserialize_with = "deserialize_name")]指定了自定义的序列化和反序列化方法。serialize_name函数将名称转换为大写字母,deserialize_name函数将名称转换为小写字母。

序列化和反序列化枚举

Serde 支持序列化和反序列化枚举类型。例如,我们定义一个Animal枚举,包含狗和猫两种类型:

1
2
3
4
5
6
7
use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
enum Animal {
    Dog { name: String, age: u32 },
    Cat { name: String, age: u32 },
}

在序列化和反序列化枚举类型时,需要使用#[serde(tag = "type")]指定枚举类型的标签,例如:

1
2
3
4
5
6
7
8
9
use serde_json;

let dog = Animal::Dog { name: "Tom".to_owned(), age: 3 };
let json = serde_json::to_string(&dog).unwrap();
println!("{}", json); // {"type":"Dog","name":"Tom","age":3}

let json = r#"{"type":"Dog","name":"Tom","age":3}"#;
let dog: Animal = serde_json::from_str(json).unwrap();
println!("{:?}", dog); // Dog { name: "Tom", age: 3 }

序列化和反序列化结构体中的 Option

Serde 支持序列化和反序列化结构体中的Option类型。例如,我们定义一个Animal结构体,包含名称和年龄两个字段,其中名称可以为空:

1
2
3
4
5
6
7
use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
struct Animal {
    name: Option<String>,
    age: u32,
}

在序列化和反序列化结构体中的Option类型时,需要使用#[serde(skip_serializing_if = "Option::is_none")]指定当Option值为None时,不进行序列化。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
use serde_json;

let animal = Animal { name: Some("Tom".to_owned()), age: 3 };
let json = serde_json::to_string(&animal).unwrap();
println!("{}", json); // {"name":"Tom","age":3}

let animal = Animal { name: None, age: 3 };
let json = serde_json::to_string(&animal).unwrap();
println!("{}", json); // {"age":3}

let json = r#"{"age":3}"#;
let animal: Animal = serde_json::from_str(json).unwrap();
println!("{:?}", animal); // Animal { name: None, age: 3 }

序列化和反序列化结构体中的 Vec

Serde 支持序列化和反序列化结构体中的Vec类型。例如,我们定义一个Zoo结构体,包含多个Animal

1
2
3
4
5
6
use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
struct Zoo {
    animals: Vec<Animal>,
}

在序列化和反序列化结构体中的Vec类型时,Serde 会自动处理序列化和反序列化。例如:

1
2
3
4
5
6
7
8
9
10
11
12
use serde_json;

let zoo = Zoo { animals: vec![
    Animal { name: "Tom".to_owned(), age: 3 },
    Animal { name: "Jerry".to_owned(), age: 2 },
] };
let json = serde_json::to_string(&zoo).unwrap();
println!("{}", json); // {"animals":[{"name":"Tom","age":3},{"name":"Jerry","age":2}]}

let json = r#"{"animals":[{"name":"Tom","age":3},{"name":"Jerry","age":2}]}"#;
let zoo: Zoo = serde_json::from_str(json).unwrap();
println!("{:?}", zoo); // Zoo { animals: [Animal { name: "Tom", age: 3 }, Animal { name: "Jerry", age: 2 }] }

序列化和反序列化结构体中的 HashMap

Serde 支持序列化和反序列化结构体中的HashMap类型。例如,我们定义一个Zoo结构体,包含多个Animal,使用HashMap存储:

1
2
3
4
5
6
7
use std::collections::HashMap;
use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
struct Zoo {
    animals: HashMap<String, Animal>,
}

在序列化和反序列化结构体中的HashMap类型时,Serde 会自动处理序列化和反序列化。例如:

1
2
3
4
5
6
7
8
9
10
11
12
use serde_json;

let mut animals = HashMap::new();
animals.insert("Tom".to_owned(), Animal { name: "Tom".to_owned(), age: 3 });
animals.insert("Jerry".to_owned(), Animal { name: "Jerry".to_owned(), age: 2 });
let zoo = Zoo { animals };
let json = serde_json::to_string(&zoo).unwrap();
println!("{}", json); // {"animals":{"Jerry":{"name":"Jerry","age":2},"Tom":{"name":"Tom","age":3}}}

let json = r#"{"animals":{"Jerry":{"name":"Jerry","age":2},"Tom":{"name":"Tom","age":3}}}"#;
let zoo: Zoo = serde_json::from_str(json).unwrap();
println!("{:?}", zoo); // Zoo { animals: {"Tom": Animal { name: "Tom", age: 3 }, "Jerry": Animal { name: "Jerry", age: 2 }} }

总结

本教程介绍了如何使用 Serde 进行序列化和反序列化,并且介绍了如何自定义序列化和反序列化逻辑。使用 Serde 可以轻松地将 Rust 数据结构转换为任何格式,并且可以通过自定义序列化和反序列化逻辑实现更高级的功能。

知识共享许可协议

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名 TinyZ Zzh (包含链接: https://tinyzzh.github.io ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。 如有任何疑问,请 与我联系 (tinyzzh815@gmail.com)

TinyZ Zzh

TinyZ Zzh

专注于高并发服务器、网络游戏相关(Java、PHP、Unity3D、Unreal Engine等)技术,热爱游戏事业, 正在努力实现自我价值当中。

评论

  点击开始评论...