本文主要是介绍【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使用零拷贝技术)
- 有长度标记的UTF-8 字节数据(不是
- byte array -
[u8]
(字节数组)- 与字符串相似,在反序列化期间,字节数组可以是 transient, 拥有所有权, 和借用
- option
- None 或者 Value
- unit (元组)
- Rust 中
()
的类型,它表示不包含数据的匿名值
- Rust 中
- unit_struct
- 例如
struct Unit
或PhantomData<T>
,它表示不包含数据的命名值
- 例如
- 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<T>
或者HashSet<T>
- 序列化时,长度在遍历之前可能是未知的。在反序列化时,通过 查看数据 可以得知长度
- 注意,像
vec![Value::Bool(true), Value::Char('c')]
之类的同质Rust集合可以序列化为异构Serde seq,在这种情况下,包含Serde bool和Serde char。
- tuple
- 大小静态可知的异质序列
- 例如
(u8,)
或(String, u64, Vec<T>)
或[u64; 10]
- 其长度在反序列化时就已知道,无需查看数据
- tuple_struct
- 命名元组,例如
struct Rgb(u8, u8, u8)
- 命名元组,例如
- tuple_variant
- 例如 在
enum E { T(u8, u8) }
中 的E::T
- 例如 在
- map
- 大小可变的异类键值对,例如
BTreeMap <K, V>
。进行序列化时,在遍历所有条目之前,长度可能未知,也可能未知。反序列化时,通过 查看数据 可以得知长度
- 大小可变的异类键值对,例如
- 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:短横线命名法
- 根据给定的大小写约定重命名所有字段(结构)或 variants(枚举)。
-
#[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<T>(value: &T) -> Result<String, Error> whereT: ?Sized + Serialize,
-
功能:将给定的数据结构序列化为 YAML 字符串。
-
示例
fn to_string() -> Result<(), Box<dyn std::error::Error>>{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<T>(value: T) -> Result<Value, Error> whereT: Serialize,
-
功能:将 转换
T
为serde_yaml::Value
可以表示任何有效 YAML 数据的枚举。如果想要一个
Value
而不是字符串,你可以使用serde_yaml::ser::Serializer
来手动序列化你的结构体到Value
。但这样做通常比直接序列化到字符串更加复杂和低效。 -
示例
-
-
to_writer
-
原型
pub fn to_writer<W, T>(writer: W, value: &T) -> Result<(), Error> whereW: 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: 123456789
2 方法
-
from_reader
-
函数原型
pub fn from_reader<R, T>(rdr: R) -> Result<T, Error> whereR: 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<(), Box<dyn std::error::Error>> {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<'de, T>(v: &'de [u8]) -> Result<T, Error> whereT: Deserialize<'de>,
-
功能:从字节反序列化
-
示例
fn from_slice() {let file = "/home/wangm/rust_exercise/serde_learn/config.yaml";match fs::read(file) {Ok(f) => {let yaml_data = f.as_slice();let people: People = match serde_yaml::from_slice(yaml_data) {Ok(u) => u,Err(e) => {println!("Error parsing YAML: {}", e);return;}};print(people);}Err(_e) => {println!("file open false");}} }
-
-
from_value
-
原型
pub fn from_value<T>(value: Value) -> Result<T, Error> whereT: DeserializeOwned,
-
功能:在不知道要反序列化内容的具体类型时使用,如果你不确定 YAML 文档的确切结构,或者它可能包含多种不同的数据结构,你可以先将其解析为
serde_yaml::Value
,然后根据需要动态地决定如何进一步处理它。
-
-
from_str
-
原型
pub fn from_str<'de, T>(s: &'de str) -> Result<T, Error> whereT: Deserialize<'de>,
-
功能:从 YAML 文本字符串反序列化类型实例
-
示例
./poem.txt
内容# == Classic == # This is a shorthand to override some of the options to be backwards compatible # with `ls`. It affects the "color"->"when", "sorting"->"dir-grouping", "date" # and "icons"->"when" options. # Possible values: false, true classic: 12# == Blocks == # This specifies the columns and their order when using the long and the tree # layout. # Possible values: permission, user, group, context, size, date, name, inode, git blocks: test1233
cargo.toml
[package] name = "all_test" version = "0.1.0" edition = "2021"# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html[dependencies] serde_yaml = "0.9" //这个库是用来解析yaml文件的 serde = { version = "1.0", features = ["derive"] } // 这是一个序列化和反序列化的框架
main.rs
use std::{fs, string}; use std::path::{Path, PathBuf}; use serde::{Serialize, Deserialize};//定义结构体,yaml解析的内容是结构体 #[derive(Serialize, Deserialize, PartialEq, Debug)] // 添加序列化和反序列化的属性 pub struct Config {pub classic: i32,pub blocks: String, }fn main() -> Result<(), serde_yaml::Error> //不带返回值的还没有测试过 {let file = "./poem.txt";match fs::read(file) { //读取文件Ok(f) => {let info = String::from_utf8_lossy(&f); //获取文件内容,去除无效字符let yaml:Config = serde_yaml::from_str(&info)?; //解析yamlprintln!("{:?}",yaml);Ok(())},Err(_e) => {println!("file read false");Ok(())},} }
执行结果:
Config { classic: 12, blocks: "test1233" }
-
3 自定义序列化反序列化
若要数据类型支持序列化和反序列化,则该类型需要实现Serialize
和Deserialize
trait。
Serde提供了rust基础类型和标准库类型的Serialize
和Deserialize
实现。对于自定义类型,可以自行实现Serialize
和Deserialize
trait。另外,serde提供一个宏serde_derive
来自动为结构体类型和枚举类型生成Serialize
和Deserialize
。该特性需要rust编译器版本在1.31
及以上,并且在cargo.toml
文件配置serde依赖时,需要features
指定该特性。例如:
[dependencies]
serde = { version = "1.0", features = ["derive"] }
在代码中引用并使用:
use serde::{Serialize, Deserialize};#[derive(Serialize, Deserialize, Debug)]
struct Point {x: i32,y: i32,
}
Serializer
和Deserializer
由第三方crate提供,例如serde_json,serde_yaml等。
3.1 自定义序列化
1)代码
use serde::ser::{Serialize,SerializeStruct,}; // 序列化// #[derive(Serialize)] // 用这种方式
// 普通结构体 步骤如下
// 1. serilaize_struct
// 2. serialize_field
// 3. end
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,{let mut state = serializer.serialize_struct("Color", 3)?; // 开始序列化一个结构体state.serialize_field("r", &self.r)?; // 序列化一个结构体域state.serialize_field("g", &self.g)?;state.serialize_field("b", &self.b)?;state.end(); // 结束序列化}
}
3.2 自定义反序列化
结构体的反序列化比枚举的反序列化更复杂。枚举反序列化是直接根据类型反序列化即可,结构体的反序列化需要将反序列化的内容先变为枚举类型,在继续反序列化。
自定义反序列化器的情况:
- 非标准格式:当需要处理的数据不是标准的json、yaml、toml等时
- 复杂的数据结构:它不能直接映射到标准格式中的表示方法
- 性能优化:
- 自定义验证和错误处理:标准的序列化/反序列化库可能只提供基本的验证和错误处理机制。有时,可能需要更复杂的验证逻辑或更详细的错误报告。
- 向前/向后兼容:应用程序需要与旧版本的数据进行交互,或者需要支持不同版本的数据格
1)框架
实现Deserialize trait 来告诉serde xxx类型支持反序列化
impl Deserialize for struct_xxx {fn deserialize<D>(deserializer:D) -> Result<Self, D::Error>whereD:Deserializer<'de>,{// 各种deserializer_xxx 函数进行反序列化deserializer.deserializer_xxx();}
}
遍历访问者
// 自定义反序列化器
struct xxxVisitor;impl<'de> Visitor<'de> for xxxVisitor {type Value = xxx;fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {}fn visit_xxx();}
2)代码
use serde::{Deserialize, Deserializer,};#[derive(Debug)]
enum Age { Numeric(u64), // Numeric,Child,
} #[derive(Deserialize, Debug)]
struct Person { name: String, age: Age, hobbies: Vec<String>,
} // 由于枚举可能包含不同的JSON表示形式,您可能需要提供一个自定义的反序列化函数
// 例如,如果您希望"age"字段可以是一个数字或一个字符串(如"child")
impl<'de> Deserialize<'de> for Age { fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: serde::Deserializer<'de>, { struct AgeVisitor; impl<'de> serde::de::Visitor<'de> for AgeVisitor { type Value = Age; fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { formatter.write_str("a number or 'child' string") } fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E> // 默认类型是64 改成u32后解析报错where E: serde::de::Error, { Ok(Age::Numeric(value)) } fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> where E: serde::de::Error, { if value == "child" { Ok(Age::Child) } else { Err(serde::de::Error::custom(format!("invalid age: {}", value))) } } // 如果需要支持其他类型,可以添加更多的visit方法 } deserializer.deserialize_any(AgeVisitor) }
} pub fn custom_deserialize() { let json = r#" { "name": "Alice", "age": "child", "hobbies": ["reading", "swimming"] } "#; let json2 = r#" { "name": "Alice", "age": 8, "hobbies": ["reading", "swimming"] } "#; let person: Person = serde_yaml::from_str(json).unwrap(); println!("{:#?}", person); let person: Person = serde_yaml::from_str(json2).unwrap(); println!("{:#?}", person);
}
程序完整代码
serde_learn
参考链接
[1]https://whiteccinn.github.io/2021/04/13/Rust%E8%AF%AD%E8%A8%80/rust-%E5%BA%8F%E5%88%97%E5%8C%96%E6%A1%86%E6%9E%B6serde/
[2]官方文档
[3]Rust 序列化反序列框架 Serde
这篇关于【rust 第三方库】serde 序列化反序列化框架的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!