【rust 第三方库】serde 序列化反序列化框架

2024-06-12 1017阅读

文章目录

  • 1 serde 框架
    • 简介
    • Serde数据模型
      • 属性
      • 2 使用第三方库序列化(serde_yaml)
        • 2.1 序列化
          • 1 方法
          • 2.2 反序列化
            • 1 简单示例
            • 2 方法
            • 3 自定义序列化反序列化
              • 3.1 自定义序列化
              • 3.2 自定义反序列化
              • 程序完整代码
              • 参考链接

                1 serde 框架

                官网:https://serde.rs/

                【rust 第三方库】serde 序列化反序列化框架
                (图片来源网络,侵删)

                作用:可以将结构体、枚举、向量、哈希表等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 方法

                                                                            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: 123456789
                                                                            

                                                                            2 方法

                                                                            1. 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
VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]