Serde是一个用于高效、通用的对 Rust 数据结构进行序列化和反序列化框架,也是 Rust 程序开发过程中最常用的库之一。
不同于其他变成语言需要依赖运行时或者反射来对数据进行序列化,Serde 则是建立的 Rust 强大的 Trait 系统之上,让我们能够写出更加高效的序列化、反序列化代码。
目前 Serde 生态非常丰富,已经支持很多类型,包括我们常见的 json 、 Yaml 、 Toml 、 Csv 、 Bson 等,还有其他的比如 URL 、 MessagePack 等。
快速入门
我们以 json 为例,为了让我们的数据结构能够支持序列化和反序列化,需要引入 serde 依赖。
命令行添加:
# 添加serde依赖
cargo add serde --features derive
# 添加支持 json 的依赖
cargo add serde_json
您也可以直接编辑 Cargo.toml
,添加以下内容:
[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
假如代码如下:
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]
struct Point {
x: i32,
y: i32,
}
fn main() {
let point = Point { x: 1, y: 2 };
let serialized = serde_json::to_string(&point).unwrap();
// 输出结果: serialized = {"x":1,"y":2}
println!("serialized = {}", serialized);
let deserialized: Point = serde_json::from_str(&serialized).unwrap();
// 输出结果: deserialized = Point { x: 1, y: 2 }
println!("deserialized = {:?}", deserialized);
}
文件中我们在结构体 Point
上面添加了 #[derive(Serialize, Deserialize, Debug)]
,三个 derive 分别代表:
Serialize
: 为结构体添加序列化支持Deserialize
: 为架构体添加反序列化支持Debug
: 这个与 Serde 无关,平时很常见,添加 Debug 输出支持。
属性说明
Serde支持大量的属性配置,用来实现更多自定义的序列化、反序列化配置。这些属性需要 Rust 编译器版本在1.15或以上。
Serde 的属性主要有三类:
- 容器属性: 主要应用于struct 和 enum 上的声明
- 变体属性: 主要在 enum 的各种变体上声明
- 字段属性:主要在 struct 或者 enum 变体的字段上声明
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)] // <-- 这是一个容器属性
struct S {
#[serde(default)] // <-- 这是一个字段属性
f: i32,
}
#[derive(Serialize, Deserialize)]
#[serde(rename = "e")] // <-- 这还是一个容器属性
enum E {
#[serde(rename = "a")] // <-- 这是一个变体属性
A(String),
}
请注意,单个结构体、枚举体、变体或者字段可能会同时具备多个属性。
容器属性
#[serde(rename = "name")]
使用给定的名字进行序列化或者反序列化,而不是使用 Rust 结构内的名字。同时允许我们为序列化或反序列化指定单独的名称。
#[serde(rename(serialize = "ser_name"))]
#[serde(rename(deserialize = "de_name"))]
#[serde(rename(serialize = "ser_name", deserialize = "de_name"))]
#[serde(rename_all = "...")]
重命名所有的字段(如果是结构体)或变体(如果是枚举体)。可能的值有 "lowercase"
, "UPPERCASE"
, "PascalCase"
, "camelCase"
, "snake_case"
, "SCREAMING_SNAKE_CASE"
, "kebab-case"
, "SCREAMING-KEBAB-CASE"。
我们也可以为序列化、反序列化单独指定规则:
#[serde(rename_all(serialize = "..."))]
#[serde(rename_all(deserialize = "..."))]
#[serde(rename_all(serialize = "...", deserialize = "..."))]
示例:
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "UPPERCASE")]
struct User {
name: String,
age: u8,
sex: Sex,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
enum Sex {
Male, // 男性
FeMale, // 女性
Unknown, // 未知
}
fn main() {
let user = User {
name: "Tom".to_string(),
age: 20,
sex: Sex::Male,
};
let serialized = serde_json::to_string(&user).unwrap();
// 输出结果: serialized = {"NAME":"Tom","AGE":20,"SEX":"MALE"}
println!("serialized = {}", serialized);
let deserialized: User = serde_json::from_str(&serialized).unwrap();
// 输出结果: deserialized = User { name: "Tom", age: 20, sex: Male }
println!("deserialized = {:?}", deserialized);
}
#[serde(rename_all_fields = "...")]
对 enum 变体中的结构体字段进行重命名,可支持的值有 "lowercase"
, "UPPERCASE"
, "PascalCase"
, "camelCase"
, "snake_case"
, "SCREAMING_SNAKE_CASE"
, "kebab-case"
, "SCREAMING-KEBAB-CASE"。
我们也可以为序列化、反序列化单独指定规则:
#[serde(rename_all_fields(serialize = "..."))]
#[serde(rename_all_fields(deserialize = "..."))]
#[serde(rename_all_fields(serialize = "...", deserialize = "..."))]
示例:
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all_fields = "UPPERCASE")]
enum Car {
Benz { model: String, price: f64 },
BMW { model: String, price: f64 },
Audi { model: String, price: f64 },
}
fn main() {
let car = Car::Benz {
model: "S500".to_string(),
price: 100.0,
};
let serialized = serde_json::to_string(&car).unwrap();
// 输出结果: serialized = {"Benz":{"MODEL":"S500","PRICE":100.0}}
println!("serialized = {}", serialized);
let deserialized: Car = serde_json::from_str(&serialized).unwrap();
// 输出结果: deserialized = Benz { model: "S500", price: 100.0 }
println!("deserialized = {:?}", deserialized);
}
#[serde(deny_unknown_fields)]
在反序列化时,遇到未知字段会报错。当这个属性不存在时,默认情况下,遇到未知字段将会被忽略。
注意这个属性不能和flatten
一起使用,不管是在外部结构或者展开后的结构上面。
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
struct Point {
x: i32,
y: i32,
}
fn main() {
let point = Point { x: 1, y: 2 };
let serialized = serde_json::to_string(&point).unwrap();
// 输出结果: serialized = {"x":1,"y":2}
println!("serialized = {}", serialized);
let deserialized: Point = serde_json::from_str(&serialized).unwrap();
// 输出结果: deserialized = Point { x: 1, y: 2 }
println!("deserialized = {:?}", deserialized);
let json = r#"{"x":1,"y":2, "z": 3}"#;
let deserialized_json: Point = serde_json::from_str(&json).unwrap();
// 会报错:called `Result::unwrap()` on an `Err` value: Error("unknown field `z`, expected `x` or `y`", line: 1, column: 17)
println!("deserialized_json = {:?}", deserialized_json);
}
由于我们为Point
添加了#[serde(deny_unknown_fields)]
属性,而最后的 json 中有一个字段z
在 Point 中并不存在,所以报错,提示 unknown field z
。
#[serde(tag = "type")]
在 enum 上:使用内部标记的枚举表示,带有给定的标记。
在具名结构体上:在结构体所有的实际字段之前,将结构体的名称(或者是serde(rename)
的值)序列化为指定的 key 。
示例1:对于具名结构体,只添加tag
参数,会在 json 中添加tag
对应的只为 key,struct 的类型为 value 的字段。
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "type")]
struct Point {
x: i32,
y: i32,
}
fn main() {
let point = Point { x: 1, y: 2 };
let serialized = serde_json::to_string(&point).unwrap();
// 输出结果: serialized = {"type":"Point","x":1,"y":2}
println!("serialized = {}", serialized);
}
示例2:对于具名结构体,当我们同时添加tag
和rename
,序列化结果中会增加以tag
值为 key,以rename
值为 value 的新字段。
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "type", rename = "PointType")]
struct Point {
x: i32,
y: i32,
}
fn main() {
let point = Point { x: 1, y: 2 };
let serialized = serde_json::to_string(&point).unwrap();
// 输出结果: serialized = {"type":"PointType","x":1,"y":2}
println!("serialized = {}", serialized);
}
示例3: 对于一个 enum,会增加tag
值为key,变体类型为值的新 key 。
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "type")]
enum Sex {
Male, // 男性
FeMale, // 女性
Unknown, // 未知
}
fn main() {
let sex = Sex::FeMale;
let serialized = serde_json::to_string(&sex).unwrap();
// 输出结果: serialized = {"type":"FeMale"}
println!("serialized = {}", serialized);
}
#[serde(tag = "t", content = "c")]
用于 enum 类型, 会把对应变体关联的信息也序列化到content
指定的字段内。
示例:
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
#[serde(tag = "t", content = "c")]
enum DataType {
VecU8(Vec<u8>),
Str(String),
Struct { id: u32, name: String },
}
fn main() {
let data1 = DataType::VecU8(vec![1, 2, 3]);
let serialized = serde_json::to_string(&data1).unwrap();
// 输出结果: serialized = {"t":"VecU8","c":[1,2,3]}
println!("serialized = {}", serialized);
let data = DataType::Str("Hello".to_string());
let serialized = serde_json::to_string(&data).unwrap();
// 输出结果: serialized = {"t":"Str","c":"Hello"}
println!("serialized = {}", serialized);
let data = DataType::Struct {
id: 1,
name: "Tom".to_string(),
};
let serialized = serde_json::to_string(&data).unwrap();
// 输出结果: serialized = {"t":"Struct","c":{"id":1,"name":"Tom"}}
println!("serialized = {}", serialized);
}
#[serde(untagged)]
也是用于 enum 类型,不会对内容进行任何标记字段包裹。
示例:
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
#[serde(untagged)]
enum DataType {
VecU8(Vec<u8>),
Str(String),
Struct { id: u32, name: String },
}
fn main() {
let data1 = DataType::VecU8(vec![1, 2, 3]);
let serialized = serde_json::to_string(&data1).unwrap();
// 输出结果: serialized = [1,2,3]
println!("serialized = {}", serialized);
let data = DataType::Str("Hello".to_string());
let serialized = serde_json::to_string(&data).unwrap();
// 输出结果: serialized = "Hello"
println!("serialized = {}", serialized);
let data = DataType::Struct {
id: 1,
name: "Tom".to_string(),
};
let serialized = serde_json::to_string(&data).unwrap();
// 输出结果: serialized = {"id":1,"name":"Tom"}
println!("serialized = {}", serialized);
}
#[serde(bound = "T: MyTrait")]
Serialize
和Deserialize
实现的 where 子句。会替换 Serde 推断类型时的任何 Trait 。
允许为序列化和反序列化单独指定。
#[serde(bound(serialize = "T: MySerTrait"))]
#[serde(bound(deserialize = "T: MyDeTrait"))]
#[serde(bound(serialize = "T: MySerTrait", deserialize = "T: MyDeTrait"))]
???
#[serde(default)]
反序列化时,从结构的 Default 实现中 填写所有缺少的字段。
示例:
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Default)]
#[serde(default)]
struct Point {
x: i32,
y: i32,
}
fn main() {
let json = r#"{"x": 1}"#;
let point: Point = serde_json::from_str(json).unwrap();
// 输出结果: point = Point { x: 1, y: 0 }
println!("point = {:?}", point);
}
虽然我们的 json 中没有字段y
,但是犹豫我们添加了#[serde(default)]
,反序列化会为我们添加默认值。
#[serde(default = "path")]
反序列化时,使用给定函数或方法返回的对象中填写所有缺少的字段。该函数声明为 fn() -> T
。
例如,default="my_default"
将调用 my_default()
,而 default = "SomeTrait::some_default"
将调用SomeTrait::some_default()
。
示例:
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Default)]
#[serde(default = "Point::default_value")]
struct Point {
x: i32,
y: i32,
}
impl Point {
fn default_value() -> Self {
Point { x: 2, y: 2 }
}
}
fn main() {
let json = r#"{"x": 1}"#;
let point: Point = serde_json::from_str(json).unwrap();
// 输出结果: point = Point { x: 1, y: 2 }
println!("point = {:?}", point);
}
#[serde(remote = "...")]
用于远程类型派生Serialize
和 Deserialize
。
???
#[serde(transparent)]
主要用于 newtype 类型结构体,或者只有一个字段的结构体,可以去除字段名的包裹。
示例:
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]
struct UserId {
value: String,
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(transparent)]
struct UserId1 {
value: String,
}
fn main() {
let s = UserId {
value: "hello".to_string(),
};
let serialized = serde_json::to_string(&s).unwrap();
// 输出结果: serialized = {"value":"hello"}
println!("serialized = {}", serialized);
let s1 = UserId1 {
value: "hello".to_string(),
};
let serialized1 = serde_json::to_string(&s1).unwrap();
// 输出结果: serialized1 = "hello"
println!("serialized1 = {}", serialized1);
}
#[serde(from = "FromType")]
通过反序列化为FromType
,然后转换来反序列化此类型。此类型必须实现From<FromType>
,而FromType
必须实现Deserialize
。
示例:
use serde::{Deserialize, Serialize};
use std::convert::From;
#[derive(Debug, Serialize, Deserialize)]
#[serde(from = "RgbColor")]
enum Color {
Rgb(u8, u8, u8),
}
#[derive(Debug, Serialize, Deserialize)]
struct RgbColor {
r: u8,
g: u8,
b: u8,
}
impl From<RgbColor> for Color {
fn from(rgb: RgbColor) -> Self {
Color::Rgb(rgb.r, rgb.g, rgb.b)
}
}
fn main() {
let data_str = r#"{"r":128,"g":128,"b":128}"#;
let color: Color = serde_json::from_str(&data_str).unwrap();
// 输出结果: color = Rgb(128, 128, 128)
println!("color = {:?}", color);
}
#[serde(try_from = "FromType")]
通过反序列化为FromType
,然后转换来反序列化此类型。此类型必须实现TryFrom<FromType>
,而FromType
必须实现Deserialize
。
示例:
use serde::{Deserialize, Serialize};
use std::convert::TryFrom;
#[derive(Debug, Serialize, Deserialize)]
#[serde(try_from = "RgbColor")]
enum Color {
Rgb(u8, u8, u8),
}
#[derive(Debug, Serialize, Deserialize)]
struct RgbColor {
r: u8,
g: u8,
b: u8,
}
impl TryFrom<RgbColor> for Color {
type Error = String;
fn try_from(rgb: RgbColor) -> Result<Self, Self::Error> {
Ok(Color::Rgb(rgb.r, rgb.g, rgb.b))
}
}
fn main() {
let data_str = r#"{"r":128,"g":128,"b":128}"#;
let color: Color = serde_json::from_str(&data_str).unwrap();
// 输出结果: color = Rgb(128, 128, 128)
println!("color = {:?}", color);
}
#[serde(into = "IntoType")]
序列化之前,现将该类型转换为 IntoType
类型,然后再序列化。此类型必须实现 Clone
和 Into<IntoType>
, 且 IntoType
必须实现 Serialize
。
示例:
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(into = "RgbColor")]
enum Color {
Rgb(u8, u8, u8),
}
#[derive(Debug, Serialize, Deserialize)]
struct RgbColor {
r: u8,
g: u8,
b: u8,
}
impl Into<RgbColor> for Color {
fn into(self) -> RgbColor {
match self {
Color::Rgb(r, g, b) => RgbColor { r, g, b },
}
}
}
fn main() {
let color = Color::Rgb(30, 30, 30);
let serialized = serde_json::to_string(&color).unwrap();
// 输出结果: serialized = {"r":30,"g":30,"b":30}
println!("serialized = {}", serialized);
}
#[serde(crate = "...")]
指定从生成的代码中,引用 Serde API 时,要使用的 Serde crate实例的路径。这通常仅适用于从不同 crate 中的公共宏调用重新导出的Serde。
???
#[serde(expecting = "...")]
为反序列化错误消息指定自定义类型期望文本。这由容器Visitor
的生成expecting
方法使用,并作为未标记枚举的故障消息。
变体属性
#[serde(rename = "name")]
使用给定名称而不是其Rust名称序列化和反序列化此变体。
允许为序列化与反序列化指定独立名称:
#[serde(rename(serialize = "ser_name"))]
#[serde(rename(deserialize = "de_name"))]
#[serde(rename(serialize = "ser_name", deserialize = "de_name"))]
#[serde(alias = "name")]
从给定名称或其Rust名称反序列化此变体。可以重复为同一变体指定多个可能的名称。
#[serde(rename_all = "...")]
根据给定的规则约定重命名此结构变体的所有字段。
可支持的值有"lowercase"
, "UPPERCASE"
, "PascalCase"
, "camelCase"
, "snake_case"
, "SCREAMING_SNAKE_CASE"
, "kebab-case"
, "SCREAMING-KEBAB-CASE"。
允许为序列化与反序列化指定独立重命名规则:
#[serde(rename_all(serialize = "..."))]
#[serde(rename_all(deserialize = "..."))]
#[serde(rename_all(serialize = "...", deserialize = "..."))]
#[serde(skip)]
序列化或者反序列化时跳过该变体。
#[serde(skip_serializing)]
序列化时跳过该变体。尝试序列化此变体将报错。
#[serde(skip_deserializing)]
反序列化时跳过该变体。
#[serde(serialize_with = "path")]
使用与其Serialize
实现不同的函数序列化此变体。提供的函数声明需要是fn<S>(&FIELD0, &FIELD1, ..., S) -> Result<S::Ok, S::Error> where S: Serializer
。尽管它也可能是FIELD{n}
类型的泛型。与serialize_with
一起使用的变体不需要能够派生Serialize
。
FIELD{n}
存在于变体的每个字段中。因此,单元变体只有S
参数,元组/结构体变体每个字段都有一个参数。
use serde::{Deserialize, Serialize, Serializer};
#[derive(Debug, Serialize, Deserialize)]
enum Color {
#[serde(serialize_with = "serialize_rgb")]
Rgb(u8, u8, u8),
}
#[derive(Debug, Serialize, Deserialize)]
struct RgbColor {
r: u8,
g: u8,
b: u8,
}
fn serialize_rgb<S>(r: &u8, g: &u8, b: &u8, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let color = RgbColor {
r: *r,
g: *g,
b: *b,
};
color.serialize(serializer)
}
fn main() {
let data = Color::Rgb(30, 30, 30);
let serialized = serde_json::to_string(&data).unwrap();
// 输出结果: serialized = {"Rgb":{"r":30,"g":30,"b":30}}
println!("serialized = {}", serialized);
}
#[serde(deserialize_with = "path")]
使用 path
函数 进行反序列化,该序列化函数声明为:fn<'de, D>(D) -> Result<FIELDS, D::Error> where D: Deserializer<'de>
#[serde(with = "module")]
serialize_with
和deserialize_with
的组合。Serde将使用$module::serialize
作为serialize_with
的值,$module::deserialize
作为deserialize_with
的值。
#[serde(bound = "T: MyTrait")]
序列化和反序列化的where子句表示。这将替换Serde推断的任何特征范围。
同时也支持为序列化和反序列化分别指定:
#[serde(bound(serialize = "T: MySerTrait"))]
#[serde(bound(deserialize = "T: MyDeTrait"))]
#[serde(bound(serialize = "T: MySerTrait", deserialize = "T: MyDeTrait"))]
#[serde(borrow)]
和 #[serde(borrow = "'a + 'b + ...")]
使用零拷贝反序列化从反序列化程序借用该字段的数据。仅允许在newtype变体(只有一个字段的元组变体)上使用。
#[serde(other)]
如果枚举标记不是此枚举中其他变体之一的标记,则反序列化此变体。仅允许在内部标记或邻接标记枚举内的单位变体上。
例如,如果我们有一个内部标记的枚举serde(tag = "variant")
,其中包含变体A
、B
和被标记为serde(other)
的Unknown
,则在输入的"variant"
字段既不是"A"
也不是"B"
时,Unkonwn
变体将被反序列化。
#[serde(untagged)]
不会对内容进行任何标记字段包裹。untagged
的变体必须在枚举定义中排在最后。
字段属性
#[serde(rename = "name")]
使用给定名称而不是其Rust名称序列化和反序列化此字段。这对于将字段序列化为camelCase或序列化名称为保留Rust关键字的字段很有用。
允许为序列化和反序列化单独指定名称:
#[serde(rename(serialize = "ser_name"))]
#[serde(rename(deserialize = "de_name"))]
#[serde(rename(serialize = "ser_name", deserialize = "de_name"))]
#[serde(alias = "name")]
从给定名称或其Rust名称反序列化此字段。可以重复为同一字段指定多个可能的名称。
#[serde(default)]
如果反序列化时该值不存在,请使用Default::default()
生成默认值。
#[serde(default = "path")]
如果反序列化时该值不存在,则调用函数以获取默认值。给定的函数必须可以调用为fn()->T
。例如default="empty_value"
将调用empty_value()
,而default="SomeTrait::some_default"
将调用SomeTrait::some_default()
。
#[serde(flatten)]
展开该字段,也就是将该字段内部抽到当前结构。
注意:此属性不支持与使用deny_unknown_fields
的结构结合使用。外部或内部扁平化结构都不应使用该属性。
#[serde(skip)]
跳过此字段:不会序列化或反序列化它。
反序列化时,Serde将使用Default::default()
或default="…"
给出的函数来获取该字段的默认值。
#[serde(skip_serializing)]
序列化时跳过此字段,反序列化时不跳过此字段。
#[serde(skip_deserializing)]
反序列化时跳过此字段,但序列化时不跳过。
反序列化时,Serde将使用Default::default()
或default="…"
给出的函数来获取该字段的默认值。
#[serde(skip_serializing_if = "path")]
调用一个函数来确定是否跳过序列化该字段。给定的函数必须可以作为fn(&T)->bool
调用,尽管它可能是T
上的泛型。例如skip_serializing_if="Option::is_none"
如果值是 None,那么就会跳过。
#[serde(serialize_with = "path")]
使用不同于Serialize
实现的函数序列化此字段。给定函数声明需要为fn<S>(&T, S) -> Result<S::Ok, S::Error> where S: Serializer
,尽管它也可能是泛型T
。与serialize_with
一起使用的字段不需要实现Serialize
。
#[serde(deserialize_with = "path")]
使用不同于Deserialize
实现的函数对该字段进行反序列化。给定函数声明需要为fn<'de, D>(D) -> Result<T, D::Error> where D: Deserializer<'de>
,尽管它也可能是泛型T
。与deserialize_with
一起使用的字段不需要实现Deserialize
。
#[serde(with = "module")]
serialize_with
和deserialize_with
的组合。Serde将使用$module::serialize
作为serialize_with
的值,$module::deserialize
作为deserialize_with
的值。
#[serde(borrow)] and #[serde(borrow = "'a + 'b + ...")]
使用零拷贝反序列化从反序列化程序借用该字段的数据。
#[serde(bound = "T: MyTrait")]
???
序列化和反序列化的where子句表示。这将替换Serde推断的任何特征范围。
同时也支持为序列化和反序列化分别指定:
#[serde(bound(serialize = "T: MySerTrait"))]
#[serde(bound(deserialize = "T: MyDeTrait"))]
#[serde(bound(serialize = "T: MySerTrait", deserialize = "T: MyDeTrait"))]
#[serde(getter = "...")]
这在为具有一个或多个私有字段的远程类型派生Serialize
时使用。
???