【rust 第三方库】serde 序列化反序列化框架
文章目录
- 1 serde 框架
- 简介
- Serde数据模型
- 属性
- 2 使用第三方库序列化(serde_yaml)
- 2.1 序列化
- 1 方法
- 2.2 反序列化
- 1 简单示例
- 2 方法
- 3 自定义序列化反序列化
- 3.1 自定义序列化
- 3.2 自定义反序列化
- 程序完整代码
- 参考链接
1 serde 框架
官网:https://serde.rs/
(图片来源网络,侵删)作用:可以将结构体、枚举、向量、哈希表等rust数据转换为各种各式的数据(目前为16种)例如JSON、YALM、TOML等,以及将这些格式的数据转换为原始的rust数据类型
简介
Serde是主流的rust序列化、反序列化框架。设计上,基于rust的静态类型系统和元编程(宏)的能力,使Serde序列化的执行速度与手写序列化器的速度相同。
使用上及其简单
- 用户为自己的类型实现Serialize和Deserialize特质即可(大多数使用derive宏实现)
- 序列化提供商,提供Serializer和Deserializer特征的实现即可。
Serde数据模型
Serde数据模型是与rust数据结构和数据格式进行交互的API。可以将其视为Serde的类型系统,Serde将rust类型分为29种。
- 针对需要序列化的类型,用户需要实现serialize:根据rust类型调用参数Serializer上的方法,而Serializer的实现有序列化提供商提供
- 针对需要反序列化的类型,用户需要实现Deserialize:根据rust类型调用参数Serializer上的方法,传递一个实现了Visitor的类型
29种类型
- 14 基础类型
- bool
- i8, i16, i32, i64, i128
- u8, u16, u32, u64, u128
- f32, f64
- char
- string
- 有长度标记的UTF-8 字节数据(不是\0结尾的形式),可能长度为0
- 在序列化时,所有类型的字符串被同等处理。在反序列化时,有三种方案:transient, 拥有所有权, 和借用。参见《理解反序列化生命周期》,(Serde使用零拷贝技术)
- byte array -[u8] (字节数组)
- 与字符串相似,在反序列化期间,字节数组可以是 transient, 拥有所有权, 和借用
- option
- None 或者 Value
- unit (元组)
- Rust 中 () 的类型,它表示不包含数据的匿名值
- unit_struct
- 例如 struct Unit 或 PhantomData,它表示不包含数据的命名值
- unit_variant
- 例如 在 enum E { A, B } 中的 E::A 和 E::B
- newtype_struct
- 例如 struct Millimeters(u8)
- newtype_variant
- 例如 在 enum E { N(u8) } 中的 E::N
- seq
- 可变大小的异质序列
- 例如 Vec 或者 HashSet
- 序列化时,长度在遍历之前可能是未知的。在反序列化时,通过 查看数据 可以得知长度
- 注意,像 vec![Value::Bool(true), Value::Char('c')] 之类的同质Rust集合可以序列化为异构Serde seq,在这种情况下,包含Serde bool和Serde char。
- tuple
- 大小静态可知的异质序列
- 例如 (u8,) 或 (String, u64, Vec) 或 [u64; 10]
- 其长度在反序列化时就已知道,无需查看数据
- tuple_struct
- 命名元组,例如 struct Rgb(u8, u8, u8)
- tuple_variant
- 例如 在 enum E { T(u8, u8) } 中 的 E::T
- map
- 大小可变的异类键值对,例如 BTreeMap 。进行序列化时,在遍历所有条目之前,长度可能未知,也可能未知。反序列化时,通过 查看数据 可以得知长度
- struct
- 静态大小的异构键值对,其中的键是编译时常量字符串,并且在反序列化时无需查看序列化数据即可知道
- 例如 struct S { r: u8, g: u8, b: u8 }
- struct_variant
- 例如 在 enum E { S { r: u8, g: u8, b: u8 } } 中 的 E::S
属性
属性用于使用派生宏的一些配置,主要分为三类:
- 容器属性Container attributes:应用在枚举和结构体上
- 变体属性Variant attributes:应用在枚举的变体上
- 字段属性Field attributes:应用在结构体和枚举变体的 字段上
1)容器属性
-
#[serde(rename_all = "...")]
- 根据给定的大小写约定重命名所有字段(结构)或 variants(枚举)。"..." 的可选值为 "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE", "kebab-case", "SCREAMING-KEBAB-CASE"
- kebab-case:短横线命名法
-
#[serde(deny_unknown_fields)]
- 指定遇到未知字段时,在反序列化期间始终出错。
- 默认情况下,对于诸如JSON之类的自描述格式,未知字段将被忽略
2)变体属性
- #[serde(alias = "name")]
- 反序列化时,对应的别名
- 允许配置多个
- #[serde(skip)]
- 跳过序列化或反序列化此 variant
- 尝试序列化时将报错
- 尝试反序列化时将报错
3)字段属性
- #[serde(alias = "name")]
- 反序列化时,对应的别名
- 允许配置多个
- #[serde(skip)]
- 跳过此字段:不序列化或反序列化
- 反序列化时,Serde将使用 Default::default() 或 default = "..." 生成该值
2 使用第三方库序列化(serde_yaml)
2.1 序列化
1 方法
-
to_string
-
原型
pub fn to_string(value: &T) -> Result where T: ?Sized + Serialize, -
功能:将给定的数据结构序列化为 YAML 字符串。
-
示例
fn to_string() -> Result{ let people = People{ name:"Alice".to_string(), age:30, email:"123456".to_string(), }; let yaml_string = serde_yaml::to_string(&people)?; println!("{}", yaml_string); Ok(()) } -
to_value
-
原型
pub fn to_value(value: T) -> Result where T: Serialize, -
功能:将 转换T为serde_yaml::Value可以表示任何有效 YAML 数据的枚举。
如果想要一个 Value 而不是字符串,你可以使用 serde_yaml::ser::Serializer 来手动序列化你的结构体到 Value。但这样做通常比直接序列化到字符串更加复杂和低效。
-
示例
-
to_writer
-
原型
pub fn to_writer(writer: W, value: &T) -> Result where W: Write, T: ?Sized + Serialize, -
功能:将给定的数据结构作为 YAML 序列化到 IO 流中。
-
示例
fn to_writer() { let people = People{ name:"Alice".to_string(), age:2, email:"123456".to_string(), }; let mut out = Vec::new(); serde_yaml::to_writer(&mut out, &people).unwrap(); let yaml_write = out.clone(); fs::write("/home/wangm/rust_exercise/serde_learn/config.yaml", yaml_write).unwrap(); let yaml_str = String::from_utf8(out).unwrap(); println!("{}", yaml_str); }
-
-
-
2.2 反序列化
1 简单示例
#[derive(Debug,Deserialize)] pub struct People { name: String, age: u8, email:String, } fn main() { // 反序列化 let json2 = r#" { name: wangmeng, age: 2, email: 123456789 } "#; let r2: People = serde_yaml::from_str(json2).unwrap(); println!("People = {:#?}", r2); println!("people name: {}", r2.name); println!("people age: {}", r2.age); println!("people email: {}", r2.email); }执行结果:
People = People { name: "wangmeng", age: 2, email: "123456789", } people name: wangmeng people age: 2 people email: 1234567892 方法
-
from_reader
-
函数原型
pub fn from_reader(rdr: R) -> Result where R: Read, T: DeserializeOwned, -
功能:从yaml的io流中反序列化类型示例
-
示例
use std::fs::File; use std::io::Read; use std::fmt; use serde::Deserialize; use serde::ser::{Serialize, SerializeStruct, Serializer}; use serde::de::{self, Deserializer, Visitor}; fn print(people:People) { println!("{:#?}", people); println!("people name: {}", people.name); println!("people age: {}", people.age); println!("people email: {}", people.email); } fn from_reader() -> Result { println!("this is a from_reader test"); let file = File::open("/home/wangm/rust_exercise/serde_learn/config.yaml")?; let people:People = serde_yaml::from_reader(file)?; print(people); Ok(()) } fn main() { // 反序列化 let _a = from_reader(); // let file = File::open("/home/wangm/rust_exercise/serde_learn/config.yaml")?; // let people:People = serde_yaml::from_reader(file)?; // println!("{:#?}", people); // Ok(()) }config.yaml
name: Alice age: 30 email: alice@example.com
在改程序中,直接打开文件即可,将文件句柄传递给反序列化函数
-
from_slice
-
原型
pub fn from_slice Result where T: Deserialize
-
-
-
- #[serde(alias = "name")]
- #[serde(alias = "name")]
- 根据给定的大小写约定重命名所有字段(结构)或 variants(枚举)。"..." 的可选值为 "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE", "kebab-case", "SCREAMING-KEBAB-CASE"
-
- 例如 在 enum E { S { r: u8, g: u8, b: u8 } } 中 的 E::S
- 14 基础类型
