serde crate 包含两层:
data structures
: 定义了 Serialize 和 Deserialize trait 类型;data format
: data structures 保存格式;
data format 在各种单独的 serde_XX crate
中提供, 如 serde_json/serde_yaml
等,
它们实现了 data structures 的 Serialize 和 Deserialize trait。
serde 为 Rust 内置 29 种类型都提供了 data structure 实现, 所以一般只需要为自定义类型使用 #[derive]
宏来自动生成 Serialize、Deserialize 的实现即可:
Cargo.toml:
[package]
name = "my-crate"
version = "0.1.0"
authors = ["Me <[email protected]>"]
[dependencies]
serde = { version = "1.0", features = ["derive"] } # 需要开启 derive
serde_json = "1.0"
src/main.rs:
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize, Debug)]
struct Point {
x: i32,
y: i32,
}
fn main() {
let point = Point { x: 1, y: 2 };
// Convert the Point to a JSON string.
let serialized = serde_json::to_string(&point).unwrap();
// Prints serialized = {"x":1,"y":2}
println!("serialized = {}", serialized);
// Convert the JSON string back to a Point.
let deserialized: Point = serde_json::from_str(&serialized).unwrap();
// Prints deserialized = Point { x: 1, y: 2 }
println!("deserialized = {:?}", deserialized);
}
使用三类属性宏对 Serialize、Deserialize 进行更灵活的配置:
- Container attributes — 对 struct/enum 类型整体有效;
- Variant attributes — 只对 enum variant 有效;
- Field attributes — 只对 struct filed 有效;
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)] // <-- this is a container attribute
struct S {
#[serde(default)] // <-- this is a field attribute
f: i32,
}
#[derive(Serialize, Deserialize)]
#[serde(rename = "e")] // <-- this is also a container attribute
enum E {
#[serde(rename = "a")] // <-- this is a variant attribute
A(String),
}
1 Container attributes #
对 struct/enum 类型整体进行重命名(而非各字段):
- #[serde(rename = “name”)]
- #[serde(rename(serialize = “ser_name”))]
- #[serde(rename(deserialize = “de_name”))]
- #[serde(rename(serialize = “ser_name”, deserialize = “de_name”))]
rename_all: 对 struct/enum 内的各字段成员按统一风格进行重命名:
- #[serde(rename_all = “…”)]
- #[serde(rename_all(serialize = “…”))]
- #[serde(rename_all(deserialize = “…”))]
- #[serde(rename_all(serialize = “…”, deserialize = “…”))]
rename_all_fields:只用于对 enum 的 struct variant 类型的各字段重命名。
- #[serde(rename_all_fields = “…”)]
- #[serde(rename_all_fields(serialize = “…”))]
- #[serde(rename_all_fields(deserialize = “…”))]
- #[serde(rename_all_fields(serialize = “…”, deserialize = “…”))]
统一风格类型: “lowercase”, “UPPERCASE”, “PascalCase”,“camelCase”, “snake_case”, “SCREAMING_SNAKE_CASE”,“kebab-case”, “SCREAMING-KEBAB-CASE”.
fn test_serde_rename() {
use serde::{Deserialize, Serialize};
use serde_json;
// rename_all 将 enum 的各 variant 字段名称按照指定风格重写,但是
// struct variant 的各 field 字段名称不变。
#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "UPPERCASE")]
enum Message {
Request { id: String, method: String },
Response { id: String },
Unknown,
Other(u8),
}
println!(
"enum Message rename_all: struct {}, simple: {}, tuple: {}",
serde_json::to_string(&Message::Request {
id: "abc".into(),
method: "get".into()
}).unwrap(),
serde_json::to_string(&Message::Unknown).unwrap(),
serde_json::to_string(&Message::Other(8)).unwrap()
);
// enum Message rename: struct {"REQUEST":{"id":"abc","method":"get"}},
// simple: "UNKNOWN", tuple: {"OTHER":8}
// rename_all_fields 只适用于 enum,而且只是对 struct variant 的各
// field key 重命名。
#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all_fields = "UPPERCASE"]
enum MessageV2 {
Request { id: String, method: String },
Response { id: String },
Unknown,
Other(u8),
}
println!(
"enum MessageV2 rename_all_fields: struct {}, simple: {}, tuple: {}",
serde_json::to_string(&MessageV2::Request {
id: "abc".into(),
method: "get".into()
}).unwrap(),
serde_json::to_string(&MessageV2::Unknown).unwrap(),
serde_json::to_string(&MessageV2::Other(8)).unwrap()
);
// enum MessageV2 rename_all_fields: struct
// {"Request":{"ID":"abc","METHOD":"get"}}, simple: "Unknown", tuple:
// {"Other":8}
// 可以同时使用 rename_all_fields 和 rename_all, 这样各字段都是重命名
#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all_fields = "UPPERCASE", rename_all = "UPPERCASE")]
enum MessageV3 {
Request { id: String, method: String },
Response { id: String },
Unknown,
Other(u8),
}
println!(
"enum MessageV3 rename_all_fields and rename_all: struct {}, simple: {}, tuple: {}",
serde_json::to_string(&MessageV3::Request {
id: "abc".into(),
method: "get".into()
})
.unwrap(),
serde_json::to_string(&MessageV3::Unknown).unwrap(),
serde_json::to_string(&MessageV3::Other(8)).unwrap()
);
// enum MessageV3 rename_all_fields and rename_all: struct
// {"REQUEST":{"ID":"abc","METHOD":"get"}}, simple: "UNKNOWN", tuple: {"OTHER":8}
// rename_all 也适用于 struct,对它的各字段有效.
#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "UPPERCASE")]
struct Student {
name: String,
age: u8,
}
let s = Student {
name: "zhang".into(),
age: 28,
};
println!(
"serde rename_all: struct: {}",
serde_json::to_string(&s).unwrap()
);
// serde rename_all: struct: {"NAME":"zhang","AGE":28}
}
#[serde(deny_unknown_fields)]:反序列化时,如果输入中有 unknown field 则 默认忽略
,设置该属性后则报错。
注意:如果输入 field 缺失,例如没有指定 struct 的所有 field,则默认 =报错=。
序列化 enum 时:
-
对于 struct variant 或 tuple variant(onetype tuple):默认使用 map, key 为 struct field 或 tuple field 名称,value 为 map 或 onetype 值。
- tag 属性,会将 field name 作为 tag 值打平到结果 map 中,对于 tuple variant 只能使用 onetype 类型。
- content 属性,只适用于 enum 类型,而且不能有 tuple variant。
-
#[serde(tag = “type”)]
-
#[serde(tag = “t”, content = “c”)]
-
#[serde(untagged)] ,struct 默认是 untagged。
fn test_serde_tag() {
use serde::{Deserialize, Serialize};
use serde_json;
// enum: 不加 tag 时,对于 struct variant 和 tuple variant,Serialize 为
// JSON,最外层的 key 为 variant 字段名称。对于普通的
// variant,显示为字段名称字符串。
//
#[derive(Serialize, Deserialize, Debug)]
enum Message {
Request { id: String, method: String },
Response { id: String },
Unknown,
Other(u8),
}
println!(
"enum Message: struct {}, simple: {}, tuple: {}",
serde_json::to_string(&Message::Request {
id: "abc".into(),
method: "get".into()
})
.unwrap(),
serde_json::to_string(&Message::Unknown).unwrap(),
serde_json::to_string(&Message::Other(8)).unwrap()
);
// enum Message: struct {"Request":{"id":"abc","method":"get"}}, simple:
// "Unknown", tuple: {"Other":8}
// 如果加了 tag, 则不会引入最外层的 variant
// 字段名称 key,而是将该字段名称作为 tag 的 value 并打
// 平到结果中。tag 不支持 tuple variant。
#[derive(Serialize, Deserialize, Debug)]
#[serde(tag = "t")]
enum MessageV2 {
Request { id: String, method: String },
Response { id: String },
Unknown,
// called `Result::unwrap()` on an `Err` value: Error("cannot
// serialize tagged newtype variant MessageV2::Other containing an
// integer", line: 0, column: 0)
//
// Other(u8),
}
println!(
"enum MessageV2: struct: {}, simple: {}, tuple: {}",
serde_json::to_string(&MessageV2::Request {
id: "abc".into(),
method: "get".into()
})
.unwrap(),
serde_json::to_string(&MessageV2::Unknown).unwrap(),
"unsupported tuple variant with tag",
// serde_json::to_string(&MessageV2::Other(8u8)).unwrap(),
);
// enum MessageV2: struct: {"t":"Request","id":"abc","method":"get"},
// simple: {"t":"Unknown"}, tuple: unsupported tuple variant with tag
// 还可以加 content,这时 struct variant 的各字段将位于 content 的 key
// 之下。 注意:content 只能用于 enum, 而不能用于 struct。
#[derive(Serialize, Deserialize, Debug)]
#[serde(tag = "t", content = "c")]
enum MessageV3 {
Request { id: String, method: String },
Response { id: String },
Unknown,
}
println!(
"enum MessageV3: struct: {}, simple: {}, tuple: {}",
serde_json::to_string(&MessageV3::Request {
id: "abc".into(),
method: "get".into()
})
.unwrap(),
serde_json::to_string(&MessageV3::Unknown).unwrap(),
"unsupported tuple variant with tag",
// serde_json::to_string(&MessageV3::Other(8u8)).unwrap(),
);
// enum MessageV3: struct: {"t":"Request","c":{"id":"abc","method":"get"}},
// simple: {"t":"Unknown"}, tuple: unsupported tuple variant with tag
#[derive(Serialize, Deserialize, Debug)]
// 对于 struct,默认是 untagged,如果指定 tag,则用于添加一个字段,值为
// struct 类型名称。
//
// error: #[serde(content = "...")] can only be used on enums
// #[serde(tag = "t", content = "c")]
#[serde(tag = "t")]
struct Student {
name: String,
age: u8,
}
let s = Student {
name: "zhang".into(),
age: 28,
};
println!("serde tag: struct: {}", serde_json::to_string(&s).unwrap());
// serde tag: struct: {"t":"Student","name":"zhang","age":28}
}
bound 用来指定实现 Serialize 和 Deserialize Trait 的类型的限界,而不是由 serde 来进行推导:
- #[serde(bound = “T: MyTrait”)]
- #[serde(bound(serialize = “T: MySerTrait”))]
- #[serde(bound(deserialize = “T: MyDeTrait”))]
- #[serde(bound(serialize = “T: MySerTrait”, deserialize = “T: MyDeTrait”))]
#[derive(Serialize, Deserialize)]
#[serde(bound = "D: SerializeWith + DeserializeWith")]
struct WithTraits1<D, E> {
#[serde(
serialize_with = "SerializeWith::serialize_with",
deserialize_with = "DeserializeWith::deserialize_with"
)]
d: D,
#[serde(
serialize_with = "SerializeWith::serialize_with",
deserialize_with = "DeserializeWith::deserialize_with",
bound = "E: SerializeWith + DeserializeWith"
)]
e: E,
}
在进行反序列化时,如果输入的字段有缺失,默认会失败。但如果使用缺省值或调用函数生成,可以避免字段缺失报错。(序列化时,因为 Rust 要求 struct 所有字段都要初始化,所以字段不可能缺失)。 #[serde(default)] 或 #[serde(default=“path”)]
只对 struct 有效:当 deserializing 时,对于缺失的 fields 使用 struct 实现的 Default trait 来补充。
- #[serde(default)]
只对 struct 有效:当 deserializing 时,对于缺失的 fields 使用指定 path
的函数或方法来返回,函数签名必须是 fn() -> T
; 如:
default = "my_default"
调用my_default()
default = "SomeTrait::some_default"
调用SomeTrait::some_default()
- #[serde(default = “path”)]
pub fn test_serde_deserialize() {
#[derive(Serialize, Deserialize, Debug)]
enum Message {
Request { id: String, method: String },
Response { id: String },
Unknown,
Other(u8),
}
// 在 Deserialize 时,如果 filed name 大小写不一致,相当于 field
// 缺失,则报错。
//
// let m: Message =
// serde_json::from_str(r#"{"request": {"id": "abcd"}}"#).unwrap();
// println!("serde deserialize: {:?}", m);
//
// called `Result::unwrap()` on an `Err` value: Error("unknown variant
// `request`, expected one of `Request`, `Response`, `Unknown`, `Other`",
// line: 1, column: 10)
// 在 Deserialize 时,如果 filed 缺失,则报错。
//
// let m: Message =
// serde_json::from_str(r#"{"Request": {"id": "abcd"}}"#).unwrap();
// println!("serde deserialize: {:?}", m);
//
// called `Result::unwrap()` on an `Err` value: Error("missing field
// `method`", line: 1, column: 26)
// 使用 serde(default) 允许 Deserialize 时 field 缺失的情况。这时用
// field 类型的 Default 来补充。
//
// serde(default) 只适用于 struct 类型,而且该 struct 整体必须实现 Default
// trait
#[derive(Serialize, Deserialize, Debug, Default)]
#[serde(default)]
struct MessageV2 {
request: String,
response: String,
unknown: u8,
}
// 字符串多了一个 field,默认被忽略。但添加 #[serde(deny_unknown_fields)]
// 后,在遇到未知 field 时报错。
let m: MessageV2 = serde_json::from_str(
r#"{"Request": {"id": "abcd"}, "request": "abcd"}"#,
)
.unwrap();
println!("serde default: {:?}", m);
}
// 另一个例子: https://riptutorial.com/rust/example/8980/default-value-for-field
#[derive(Deserialize, Debug)]
struct Request {
// 使用 default_resource() 函数返回缺省值
#[serde(default="default_resource")]
resource: String,
// 使用 Timeout 类型的 Default trait 实现来补齐缺省值
#[serde(default)]
timeout: Timeout,
// 使用 Priority 类型的关联方法 lowest() 返回缺省值
#[serde(default="Priority::lowest")]
priority: Priority,
}
fn default_resource() -> String {
"/".to_string()
}
#[derive(Deserialize, Debug)]
struct Timeout(u32);
impl Default for Timeout {
fn default() -> Self {
Timeout(30)
}
}
#[derive(Deserialize, Debug)]
enum Priority { ExtraHigh, High, Normal, Low, ExtraLow }
impl Priority {
fn lowest() -> Self { Priority::ExtraLow }
}
fn main() {
let json = r#"
[
{
"resource": "/users"
},
{
"timeout": 5,
"priority": "High"
}
]
"#;
let requests: Vec<Request> = serde_json::from_str(json).unwrap();
// The first request has resource="/users", timeout=30, priority=ExtraLow
println!("{:?}", requests[0]);
// The second request has resource="/", timeout=5, priority=High
println!("{:?}", requests[1]);
}
#[serde(remote = “…”)] 和 #[serde(with = “…”)] 主要解决为其它 crate 中定义的类型实现 Serialize 和 Deserialize 的问题(由于 Rust 的 Orphan rule 的限制)。
- 在本 crate 中定义一个类型 AR,可以将其它 crate 中的类型 A 转换为 AR;
- 使用 remote 来修饰本 crate 的自定义类型 AR,它的值为其它 crate 中的类型 A。
- 在本 crate 中定义其它待 ser/de 的类型 S,内部字段使用 AR 类型,但是使用 with 修饰,值为 AR;
后续序列化和反序列化 S 时,均使用 AR 的结果,但是自动转换为 A。
// https://serde.rs/remote-derive.html
// Pretend that this is somebody else's crate, not a module.
mod other_crate {
// Neither Serde nor the other crate provides Serialize and Deserialize
// impls for this struct.
pub struct Duration {
pub secs: i64,
pub nanos: i32,
}
}
////////////////////////////////////////////////////////////////////////////////
use other_crate::Duration;
use serde::{Serialize, Deserialize};
// Serde calls this the definition of the remote type. It is just a copy of the
// remote data structure. The `remote` attribute gives the path to the actual
// type we intend to derive code for.
#[derive(Serialize, Deserialize)]
#[serde(remote = "Duration")]
struct DurationDef {
secs: i64,
nanos: i32,
}
// Provide a conversion to construct the remote type.
impl From<DurationDef> for Duration {
fn from(def: DurationDef) -> Duration {
Duration::new(def.secs, def.nanos)
}
}
// Now the remote type can be used almost like it had its own Serialize and
// Deserialize impls all along. The `with` attribute gives the path to the
// definition for the remote type. Note that the real type of the field is the
// remote type, not the definition type.
#[derive(Serialize, Deserialize)]
struct Process {
command_line: String,
#[serde(with = "DurationDef")] // with 类型可以使用 From 转换为 Duration 类型
wall_time: Duration,
}
#[serde(transparent)]:只能用于只有一个 field 的 struct,在序列化时忽略该 field key,只输出值。
#[derive(Serialize, Deserialize, Debug)]
#[serde(transparent)]
struct MessageV3 {
f: u8,
};
let m = serde_json::to_string(&MessageV3 { f: 8u8 }).unwrap();
println!("serde transparet: {}", m);
// 不加 #[serde(transparent)]: serde transparet: {"f":8}
//
// 加 #[serde(transparent)]:serde transparet: 8
#[serde(from = “FromType”)] 和 #[serde(try_from = “FromType”)] :反序列化使用,将字符串先反序列化为 FromType 类型值 value(FromType 需要实现 Deserialize),然后再转换为修饰的类型值。修饰的类型值需要实现 From<FromType>.
#[serde(into = “IntoType”)]:序列化时使用,修饰的类型需要实现 Clone 和 Into<IntoType>, 序列化时先将修饰的类型值转换为 IntoType 类型值,然后对它进行序列化(IntoType 需要实现 Serialize)。
- #[serde(crate = “…”)]
- #[serde(expecting = “…”)]
2 Variant attributes #
针对 enum 内各 variant 使用。
指定序列化和反序列化时,对该 variant 字段名称(不含 struct variant 的各内部 field 名称)进行重命名:
- #[serde(rename = “name”)]
- #[serde(rename(serialize = “ser_name”))]
- #[serde(rename(deserialize = “de_name”))]
- #[serde(rename(serialize = “ser_name”, deserialize = “de_name”))]
反序列化时使用,从这个 name 或字段名来解析字段内容。可以指定多次,实现多个别名。
- #[serde(alias = “name”)]:
只对 struct variant 有效,用于将 struct 中各 field 按照指定的风格进行重命名: “lowercase”,“UPPERCASE”, “PascalCase”, “camelCase”, “snake_case”, “SCREAMING_SNAKE_CASE”, “kebab-case”,“SCREAMING-KEBAB-CASE”:
- #[serde(rename_all = “…”)]
- #[serde(rename_all(serialize = “…”))]
- #[serde(rename_all(deserialize = “…”))]
- #[serde(rename_all(serialize = “…”, deserialize = “…”))]
序列化或反序列化时忽略该 variant。
- #[serde(skip)]
- #[serde(skip_serializing)]
- #[serde(skip_deserializing)]
使用指定的函数来对 variant 字段进行序列化和反序列化,而不是字段类型默认实现的 Serialize 或 Deserialize trait:
-
#[serde(serialize_with = “path”)]: path 对应的函数签名(FIELDXX 为 variant 字段类型)
fn<S>(&FIELD0, &FIELD1, ..., S) -> Result<S::Ok, S::Error> where S: Serializer
-
#[serde(deserialize_with = “path”)]: path 对应的函数签名(D 为 variant 字段类型, FIELDS 为字段类型)
fn<'de, D>(D) -> Result<FIELDS, D::Error> where D: Deserializer<'de>
-
#[serde(with = “module”)]: module 需要定义 $module::serialize 和 $module::deserialize 函数,分别用于序列化和反序列化;
// 例子
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
use serde::{Deserialize, Deserializer};
#[derive(Debug, Deserialize)]
struct WrappedI32(#[serde(deserialize_with = "callback")] i32);
// callback, as provided by the external library
fn callback<'de, D>(deserializer: D) -> Result<i32, D::Error> where D: Deserializer<'de>,
{
Ok(i32::deserialize(deserializer)? * 2)
}
// Our final output struct, that we want to get after parsing the JSON
#[derive(Debug, Deserialize)]
struct S {
#[serde(deserialize_with = "callback_opt")]
s: Option<i32>,
#[serde(deserialize_with = "callback_opt")]
s2: Option<i32>
}
pub fn callback_opt<'de, D>(deserializer: D) -> Result<Option<i32>, D::Error> where D: Deserializer<'de>,
{
Option::<WrappedI32>::deserialize(deserializer)
.map(|opt_wrapped: Option<WrappedI32>| {
opt_wrapped.map(|wrapped: WrappedI32| wrapped.0)
})
}
fn main() {
println!("{:?}", serde_json::from_str::<S>(r#"{"s": 42, "s2": null}"#));
}
// 另一个例子
#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;
extern crate chrono;
use chrono::NaiveDate;
// 该 module 下需要定义 serialize() 和 deserialize() 两个函数
mod date_serde {
use chrono::NaiveDate;
use serde::{self, Deserialize, Serializer, Deserializer};
// date 为要序列化的 variant 类型
pub fn serialize<S>(date: &Option<NaiveDate>, s: S) -> Result<S::Ok, S::Error>
where S: Serializer {
if let Some(ref d) = *date {
return s.serialize_str(&d.format("%Y-%m-%d").to_string())
}
s.serialize_none()
}
// Result 中的 Option<NaiveDate> 为反序列化生成的 variant 类型
pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<NaiveDate>, D::Error>
where D: Deserializer<'de> {
let s: Option<String> = Option::deserialize(deserializer)?;
if let Some(s) = s {
return Ok(Some(NaiveDate::parse_from_str(&s, "%Y-%m-%d").map_err(serde::de::Error::custom)?))
}
Ok(None)
}
}
#[derive(Debug, Serialize, Deserialize)]
struct Test {
pub i: u64,
#[serde(with = "date_serde")] // data_serde module
pub date: Option<NaiveDate>,
}
fn main() {
let mut test: Test = serde_json::from_str(r#"{"i": 3, "date": "2015-02-03"}"#).unwrap();
assert_eq!(test.i, 3);
assert_eq!(test.date, Some(NaiveDate::from_ymd(2015, 02, 03)));
test = serde_json::from_str(r#"{"i": 5}"#).unwrap();
assert_eq!(test.i, 5);
assert_eq!(test.date, None);
}
各字段类型需要实现 S: Serializer 和 D: Deserializer,该限界是 serde 自动推导的。但是如果使用自定义的序列化或反序列化函数,则该函数是泛型函数,泛型类型参数为字段的类型,使用 bound 可以为该类型定义新的限界约束。
- #[serde(bound = “T: MyTrait”)]
- #[serde(bound(serialize = “T: MySerTrait”))]
- #[serde(bound(deserialize = “T: MyDeTrait”))]
- #[serde(bound(serialize = “T: MySerTrait”, deserialize = “T: MyDeTrait”))]
// https://riptutorial.com/rust/example/18224/handwritten-generic-type-bounds
extern crate serde;
extern crate serde_json;
#[macro_use] extern crate serde_derive;
use serde::de::{self, Deserialize, Deserializer};
use std::fmt::Display;
use std::str::FromStr;
#[derive(Deserialize, Debug)]
struct Outer<'a, S, T: 'a + ?Sized> {
// When deriving the Deserialize impl, Serde would want to generate a bound `S: Deserialize`
// on the type of this field. But we are going to use the type's `FromStr` impl instead of its
// `Deserialize` impl by going through `deserialize_from_str`, so we override the
// automatically generated bound by the one required for `deserialize_from_str`.
// deserialize_from_str() 是泛型反序列化函数,其中一个泛型类型是 S,
// 这里指定 S 的限界。
#[serde(deserialize_with = "deserialize_from_str")]
#[serde(bound(deserialize = "S: FromStr, S::Err: Display"))]
// 对 S 类型按照 bound 的参数进行限界。
//(如果未指定 bound,S 默认限界为 Deserialize)
s: S,
// Here Serde would want to generate a bound `T: Deserialize`. That is a stricter condition
// than is necessary. In fact, the `main` function below uses T=str which does not implement
// Deserialize. We override the automatically generated bound by a looser one.
#[serde(bound(deserialize = "Ptr<'a, T>: Deserialize"))]
// 对 Ptr<'a, T> 类型进行限界,该类型需要实现 Deserialize
ptr: Ptr<'a, T>,
}
/// Deserialize a type `S` by deserializing a string, then using the `FromStr` impl of `S` to
/// create the result. The generic type `S` is not required to implement `Deserialize`.
fn deserialize_from_str<S, D>(deserializer: D) -> Result<S, D::Error>
where S: FromStr,
S::Err: Display,
D: Deserializer
{
let s: String = try!(Deserialize::deserialize(deserializer));
S::from_str(&s).map_err(|e| de::Error::custom(e.to_string()))
}
/// A pointer to `T` which may or may not own the data. When deserializing
/// we always want to produce owned data.
#[derive(Debug)]
enum Ptr<'a, T: 'a + ?Sized> {
Ref(&'a T),
Owned(Box<T>),
}
impl<'a, T: 'a + ?Sized> Deserialize for Ptr<'a, T>
where Box<T>: Deserialize
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer
{
let box_t = try!(Deserialize::deserialize(deserializer));
Ok(Ptr::Owned(box_t))
}
}
fn main() {
let j = r#"
{
"s": "1234567890",
"ptr": "owned"
}
"#;
let result: Outer<u64, str> = serde_json::from_str(j).unwrap();
// result = Outer { s: 1234567890, ptr: Owned("owned") }
println!("result = {:?}", result);
}
对于有 lifetime 的类型,反序列化时,&str 和 &[u8] 类型 field,serde 默认 borrow。对于其它类型 field 需要明确使用 #[serde(borrow)]
来进行 borrow,同时可以指定
borrow 的 lifetime 约束:#[serde(borrow = “‘a + ‘b + …”)]
// https://serde.rs/lifetimes.html#borrowing-data-in-a-derived-impl
use serde::Deserialize;
use std::borrow::Cow;
#[derive(Deserialize)]
struct Inner<'a, 'b> {
// &str and &[u8] are implicitly borrowed.
username: &'a str,
// Other types must be borrowed explicitly.
#[serde(borrow)]
comment: Cow<'b, str>,
}
#[derive(Deserialize)]
struct Outer<'a, 'b, 'c> {
owned: String,
#[serde(borrow)]
inner: Inner<'a, 'b>,
// This field is never borrowed.
not_borrowed: Cow<'c, str>,
}
// The lifetimes 'a and 'b are borrowed while 'c is not.
impl<'de: 'a + 'b, 'a, 'b, 'c> Deserialize<'de> for Outer<'a, 'b, 'c> {
/* ... */
}
use std::marker::PhantomData;
// This struct borrows the first two lifetimes but not the third.
#[derive(Deserialize)]
struct Three<'a, 'b, 'c> {
a: &'a str,
b: &'b str,
c: PhantomData<&'c str>,
}
#[derive(Deserialize)]
struct Example<'a, 'b, 'c> {
// Borrow 'a and 'b only, not 'c.
#[serde(borrow = "'a + 'b")]
three: Three<'a, 'b, 'c>,
}
#[serde(other)]:需要和 serde(tag = “xx “) 连用,如 serde(tag = “variant”),当 enum 包含 A,B 和 Unkonwn 三个 variant,且 Unknown 被标记为 serde(other)时, 当反序列化时,如果 variant field 值不为 A 或 B 时,则当作 Unknown 来反序列化。
#[serde(untagged)] 强制将该 variant field 使用 untagged 类型值进行序列化和反序列化(如不管是否设置 serde(tag = “xx”) ):
3 Field attributes #
针对 struct 成员使用。
对 struct field 进行重命名:
- #[serde(rename = “name”)]
- #[serde(rename(serialize = “ser_name”))]
- #[serde(rename(deserialize = “de_name”))]
- #[serde(rename(serialize = “ser_name”, deserialize = “de_name”))]
extern crate serde;
extern crate serde_json;
#[macro_use] extern crate serde_derive;
#[derive(Serialize)]
struct Person {
#[serde(rename="firstName")]
first_name: String,
#[serde(rename="lastName")]
last_name: String,
}
fn main() {
let person = Person {
first_name: "Joel".to_string(),
last_name: "Spolsky".to_string(),
};
let json = serde_json::to_string_pretty(&person).unwrap();
// Prints:
//
// {
// "firstName": "Joel",
// "lastName": "Spolsky"
// }
println!("{}", json);
}
反序列化时 field 别名,可以指定多个:
- #[serde(alias = “name”)]
反序列化时,如果 field 不存在,则使用 Default::default():
- #[serde(default)]
反序列化时,如果 field 不存在,调用 path 对象的函数来获得缺省值:
- #[serde(default = “path”)]
序列化或反序列化时,将嵌入的 struct 类型 field 或 map 打平到所属 struct 中:
- #[serde(flatten)]
// https://serde.rs/attr-flatten.html
#[derive(Serialize, Deserialize)]
struct Pagination {
limit: u64,
offset: u64,
total: u64,
}
#[derive(Serialize, Deserialize)]
struct Users {
users: Vec<User>,
#[serde(flatten)]
pagination: Pagination,
}
// {
// "limit": 100,
// "offset": 200,
// "total": 1053,
// "users": [
// {"id": "49824073-979f-4814-be10-5ea416ee1c2f", "username": "john_doe"},
// ...
// ]
// }
use std::collections::HashMap;
use serde::{Serialize, Deserialize};
use serde_json::Value;
#[derive(Serialize, Deserialize)]
struct User {
id: String,
username: String,
#[serde(flatten)]
extra: HashMap<String, Value>,
}
// {
// "id": "49824073-979f-4814-be10-5ea416ee1c2f",
// "username": "john_doe",
// "mascot": "Ferris"
// }
序列化时,忽略该 field 的值,但是反序列化时使用缺省值(而不看实际传入的值):
- #[serde(skip)] // 反序列化时使用 Default::default() 或 default = “…” 配置。
- #[serde(skip_serializing)]
- #[serde(skip_deserializing)]
- #[serde(skip_serializing_if = “path”)] // path 例如 Option::is_none
extern crate serde;
extern crate serde_json;
#[macro_use] extern crate serde_derive;
use std::collections::BTreeMap as Map;
#[derive(Serialize)]
struct Resource {
// Always serialized.
name: String,
// Never serialized.
#[serde(skip_serializing)]
hash: String,
// Use a method to decide whether the field should be skipped.
#[serde(skip_serializing_if="Map::is_empty")]
metadata: Map<String, String>,
}
fn main() {
let resources = vec![
Resource {
name: "Stack Overflow".to_string(),
hash: "b6469c3f31653d281bbbfa6f94d60fea130abe38".to_string(),
metadata: Map::new(),
},
Resource {
name: "GitHub".to_string(),
hash: "5cb7a0c47e53854cd00e1a968de5abce1c124601".to_string(),
metadata: {
let mut metadata = Map::new();
metadata.insert("headquarters".to_string(),
"San Francisco".to_string());
metadata
},
},
];
let json = serde_json::to_string_pretty(&resources).unwrap();
// Prints:
//
// [
// {
// "name": "Stack Overflow"
// },
// {
// "name": "GitHub",
// "metadata": {
// "headquarters": "San Francisco"
// }
// }
// ]
println!("{}", json);
}
使用指定函数来序列化或反序列化值:
-
#[serde(serialize_with = “path”)] path 函数签名:
fn<S>(&T, S) -> Result<S::Ok, S::Error> where S: Serializer
-
#[serde(deserialize_with = “path”)] path 函数签名:
fn<'de, D>(D) -> Result<T, D::Error> where D: Deserializer<'de>
-
#[serde(with = “module”)] module 必须同时定义 $module::serialize 和 $module::deserialize 函数。
-
#[serde(bound = “T: MyTrait”)]
-
#[serde(bound(serialize = “T: MySerTrait”))]
-
#[serde(bound(deserialize = “T: MyDeTrait”))]
-
#[serde(bound(serialize = “T: MySerTrait”, deserialize = “T: MyDeTrait”))]
-
#[serde(borrow)] and #[serde(borrow = “‘a + ‘b + …”)]
#[serde(getter = “…”)] 序列化时使用,remote type 且该 type 的 field 非 pub 时,指定获得该 field 值的 getter 函数。
// https://serde.rs/remote-derive.html
// Pretend that this is somebody else's crate, not a module.
mod other_crate {
// Neither Serde nor the other crate provides Serialize and Deserialize
// impls for this struct. Oh, and the fields are private.
pub struct Duration {
secs: i64,
nanos: i32,
}
impl Duration {
pub fn new(secs: i64, nanos: i32) -> Self {
Duration { secs: secs, nanos: nanos }
}
pub fn seconds(&self) -> i64 {
self.secs
}
pub fn subsec_nanos(&self) -> i32 {
self.nanos
}
}
}
////////////////////////////////////////////////////////////////////////////////
use other_crate::Duration;
use serde::{Serialize, Deserialize};
// Provide getters for every private field of the remote struct. The getter must
// return either `T` or `&T` where `T` is the type of the field.
#[derive(Serialize, Deserialize)]
#[serde(remote = "Duration")]
struct DurationDef {
#[serde(getter = "Duration::seconds")]
secs: i64,
#[serde(getter = "Duration::subsec_nanos")]
nanos: i32,
}
// Provide a conversion to construct the remote type.
impl From<DurationDef> for Duration {
fn from(def: DurationDef) -> Duration {
Duration::new(def.secs, def.nanos)
}
}
#[derive(Serialize, Deserialize)]
struct Process {
command_line: String,
#[serde(with = "DurationDef")]
wall_time: Duration,
}
4 序列化 #
自定义类型需要实现 Serialize trait 后才能被序列化,可以通过
#[derive(Serialize)]
宏来自动实现。
pub trait Serialize {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer;
}
// 示例
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize, Debug)]
struct Point {
x: i32,
y: i32,
}
fn main() {
let point = Point { x: 1, y: 2 };
// 调用 point 实现的 serialize() 方法,传入 serde_json 提供的
// Serializer trait 实现类型。
let serialized = serde_json::to_string(&point).unwrap();
println!("serialized = {}", serialized);
let deserialized: Point = serde_json::from_str(&serialized).unwrap();
println!("deserialized = {:?}", deserialized);
}
serde 为 Rust 内置 29 种类型都提供了 data structure 实现,例如 i32 类型:
impl Serialize for i32 {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
// 根据 Self 类型,调用 serialize_XX 方法。
serializer.serialize_i32(*self)
}
}
手动实现时,调用 Serializer trait 提供 serialize() 方法,传入的 serializer 是其它 serde data format 的 crate 实现的,例如 serde_json/serde_yaml crate。
核心是调用 Serialize 的各种 serialize_XX() 方法来序列化。
-
序列化 seq/map 类型:
use serde::ser::{Serialize, Serializer, SerializeSeq, SerializeMap}; impl<T> Serialize for Vec<T> where T: Serialize, { fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer, { // 序列化 顺序 类型,如 Vec/HashSet let mut seq = serializer.serialize_seq(Some(self.len()))?; for e in self { seq.serialize_element(e)?; } seq.end() } } impl<K, V> Serialize for MyMap<K, V> where K: Serialize, V: Serialize, { fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer, { // 序列化 map 类型 let mut map = serializer.serialize_map(Some(self.len()))?; for (k, v) in self { map.serialize_entry(k, v)?; } map.end() } }
-
序列化 struct 类型:
use serde::ser::{Serialize, Serializer, SerializeStruct}; struct Color { r: u8, g: u8, b: u8, } impl Serialize for Color { fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer, { // 3 is the number of fields in the struct. let mut state = serializer.serialize_struct("Color", 3)?; state.serialize_field("r", &self.r)?; // 不需要指定 field 类型 state.serialize_field("g", &self.g)?; state.serialize_field("b", &self.b)?; state.end() }
-
序列化 enum 类型:
enum E { // Use three-step process: // 1. serialize_struct_variant // 2. serialize_field // 3. end Color { r: u8, g: u8, b: u8 }, // Use three-step process: // 1. serialize_tuple_variant // 2. serialize_field // 3. end Point2D(f64, f64), // Use serialize_newtype_variant. Inches(u64), // Use serialize_unit_variant. Instance, }
5 反序列化 #
自定义类型实现 Deserialize trait 来进行反序列化,通过 #[derive(Deserialize)] 宏来自动实现:
pub trait Deserialize<'de>: Sized {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'de>;
}
手动实现时,调用 Deserializer trait 提供的 deserialize() 方法,传入的 derializer 是其它 serde data format 的 crate 实现的,例如 serde_json/serde_yaml crate。
核心是调用 deserializer 的 deserialize_XX() 方法来反序列化,这些方法的参数是一个实现 Visitor trait 的类型对象:
- Visitor 的关联类型为反序列化生成的对象类型;
- Visitor 对象需要实现 expecting() 和一系列 visit_XX() 方法,后续由 deserializer 自动调用;
- deserialize_XX() 不一定调用 Visitor 的 visit_XX() 方法,具体取决于 deserializer 的实现(如 serde_json 提供了 Deserializer 的实现,由它决定);
// 先为 i32 定义一个实现 Visitor trait 的对象, 该对象的关联类型 Value
// 与最终要解码生成的对象类型一致(这里是 i32);
use std::fmt;
use serde::de::{self, Visitor};
struct I32Visitor;
// 关联类型 Value 为 deserilize 的类型,必须要实现的方法是 expecting()
impl<'de> Visitor<'de> for I32Visitor {
type Value = i32; // 要 deserilize 的类型
// 异常时显示的字符串。
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("an integer between -2^31 and 2^31")
}
fn visit_i8<E>(self, value: i8) -> Result<Self::Value, E> where E: de::Error,
{
Ok(i32::from(value))
}
fn visit_i32<E>(self, value: i32) -> Result<Self::Value, E> where E: de::Error,
{
Ok(value)
}
fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E> where E: de::Error,
{
use std::i32;
if value >= i64::from(i32::MIN) && value <= i64::from(i32::MAX) {
Ok(value as i32)
} else {
Err(E::custom(format!("i32 out of range: {}", value)))
}
}
// Similar for other methods:
// - visit_i16
// - visit_u8
// - visit_u16
// - visit_u32
// - visit_u64
}
// 为 i32 类型定义 Deserialize 实现, Deserializer 是 serde_json/yaml
// 等提供的类型:
impl<'de> Deserialize<'de> for i32 {
fn deserialize<D>(deserializer: D) -> Result<i32, D::Error>
where D: Deserializer<'de>,
{
deserializer.deserialize_i32(I32Visitor) // 传入为 i32 定义的 Visitor
}
}
6 serde-aux crate #
serde-aux crate
提供了一系列 serde 序列化和反序列化使用的自定义函数,可以用 #[serde(with=“xxx”)]来使用它们。
bool_true Allows a bool field to be defaulted to true, rather than the normal default of false. Useful for fields where the default value should be true.
default_i16 Allows compact setting i16 field default value. default_i32 Allows compact setting i32 field default value. default_i64 Allows compact setting i64 field default value. default_u16 Allows compact setting u16 field default value. default_u32 Allows compact setting u32 field default value. default_u64 Allows compact setting u64 field default value.
deserialize_bool_from_anything Deserializes boolean from anything (string, number, boolean). If input is a string, it is expected, that it is possible to convert it to a number. The return boolean is true if the number was either 1 or 1.0 after parsing.
deserialize_cell_option_number_from_string Deserializes a Cell option number from string or a number. Same logic as “deserialize_option_number_from_string”.
deserialize_datetime_utc_from_milliseconds Deserializes a chrono::DateTime<Utc> from a milliseconds time stamp. Useful when the data is coming from a number which is not a seconds time stamp but milliseconds one. It also handles the string to number conversion if the data was passed as a string with number inside like “1519927261900”.
deserialize_datetime_utc_from_seconds Deserializes a chrono::DateTime<Utc> from a seconds time stamp. It also handles the string to number conversion if the data was passed as a string with number inside like “1519927261”.
deserialize_default_from_empty_object Deserializes default value from nullable value or empty object. If the original value is null or {}, Default::default() is used.
deserialize_default_from_null Deserializes default value from nullable value. If the original value is null, Default::default() is used.
deserialize_mutex_option_number_from_string Deserializes a Mutex option number from string or a number. Same logic as “deserialize_option_number_from_string”.
deserialize_number_from_string Deserializes a number from string or a number.
deserialize_option_number_from_string Deserializes an option number from string or a number.
deserialize_ref_cell_option_number_from_string Deserializes a RefCell option number from string or a number. Same logic as “deserialize_option_number_from_string”.
deserialize_rw_lock_option_number_from_string Deserializes a RwLock option number from string or a number. Same logic as “deserialize_option_number_from_string”.
deserialize_string_from_number Deserializes string from a number. If the original value is a number value, it will be converted to a string.
use serde_aux::field_attributes::deserialize_number_from_string;
#[derive(serde::Deserialize)]
pub struct ApplicationSettings {
#[serde(deserialize_with = "deserialize_number_from_string")]
pub port: u16,
// [...]
}
7 validator crate #
为 struct 等自定义类型的 field 引入 #[validate] 校验属性宏。
引入依赖
[dependencies]
validator = { version = "0.18", features = ["derive"] }
支持的校验规则:
-
email
-
url
-
length
const MIN_CONST: u64 = 1; const MAX_CONST: u64 = 10; #[validate(length(min = 1, max = 10))] #[validate(length(min = 1))] #[validate(length(max = 10))] #[validate(length(equal = 10))] #[validate(length(min = "MIN_CONST", max = "MAX_CONST"))]
-
range
const MAX_CONSTANT: i32 = 10; const MIN_CONSTANT: i32 = 0; #[validate(range(min = 1))] #[validate(range(min = "MIN_CONSTANT"))] #[validate(range(min = 1, max = 10))] #[validate(range(min = 1.1, max = 10.8))] #[validate(range(max = 10.8))] #[validate(range(min = "MAX_CONSTANT"))] #[validate(range(min = "crate::MAX_CONSTANT"))] #[validate(range(exclusive_min = 0.0, max = 100.0))] #[validate(range(exclusive_max = 10))]
-
must_match
#[validate(must_match(other = "password2"))]
-
contains
#[validate(contains = "gmail")] #[validate(contains(pattern = "gmail"))]
-
does_not_contain
#[validate(does_not_contain = "gmail")] #[validate(does_not_contain(pattern = "gmail"))]
-
custom
#[validate(custom(function = "validate_something"))] #[validate(custom(function = "::utils::validate_something"))]
-
regex
use once_cell::sync::Lazy; static RE_TWO_CHARS: Lazy<Regex> = Lazy::new(|| {Regex::new(r"[a-z]{2}$").unwrap()}); #[validate(regex(path = *RE_TWO_CHARS)]
-
credit_card (Requires the feature
card
to be enabled) -
non_control_character (Required the feature
unic
to be enabled) -
required: Tests whether the
Option<T>
field is Some;
消息和错误:Each validator can take 2 optional arguments in addition to their own arguments:
- message: a message to go with the error, for example if you want to do i18n
- code: each validator has a default error code (for example the regex validator code is regex) but it can be overridden if necessary, mainly needed for the custom validator
// code attribute
#[validate(email(code = "code_str"))]
#[validate(credit_card(code = "code_str"))]
#[validate(length(min = 5, max = 10, code = "code_str"))]
#[validate(regex(path = *static_regex, code = "code_str"))]
#[validate(custom(function = "custom_fn", code = "code_str"))]
#[validate(contains(pattern = "pattern_str", code = "code_str"))]
#[validate(does_not_contain(pattern = "pattern_str", code = "code_str"))]
#[validate(must_match(other = "match_value", code = "code_str"))]
// message attribute
#[validate(url(message = "message_str"))]
#[validate(length(min = 5, max = 10, message = "message_str"))]
#[validate(regex(path = *static_regex, message = "message_str"))]
#[validate(custom(function = "custom_fn", message = "message_str"))]
#[validate(contains(pattern = "pattern_str", message = "message_str"))]
#[validate(does_not_contain(pattern = "pattern_str", message = "message_str"))]
#[validate(must_match(other = "match_value", message = "message_str"))]
// both attributes
#[validate(url(message = "message", code = "code_str"))]
#[validate(email(code = "code_str", message = "message"))]
#[validate(custom(function = "custom_fn", code = "code_str", message = "message_str"))]
示例:
use serde::Deserialize;
// A trait that the Validate derive will impl
use validator::{Validate, ValidationError};
#[derive(Debug, Validate, Deserialize)]
struct SignupData {
#[validate(email)]
mail: String,
#[validate(url)]
site: String,
#[validate(length(min = 1), custom(function = "validate_unique_username"))]
#[serde(rename = "firstName")]
first_name: String,
#[validate(range(min = 18, max = 20))]
age: u32,
#[validate(range(exclusive_min = 0.0, max = 100.0))]
height: f32,
}
fn validate_unique_username(username: &str) -> Result<(), ValidationError> {
if username == "xXxShad0wxXx" {
// the value of the username will automatically be added later
return Err(ValidationError::new("terrible_username"));
}
Ok(())
}
match signup_data.validate() {
Ok(_) => (),
Err(e) => return e;
};
#[derive(Validate, Clone)]
struct Foo {
#[validate(length(equal = 5, message = "Please provide a valid foo!"))]
foo: String,
}
#[test]
fn test_message() {
let bad_foo = Foo { foo: "hi!".into() };
let err = format!("{}", bad_foo.validate().unwrap_err());
assert_eq!(err, "foo: Please provide a valid foo!");
}