当前位置:网站首页>serde - rust的序列化方案
serde - rust的序列化方案
2022-04-23 05:45:00 【许野平】
原文: Overview · Serde
翻译: kula
serde, 是rust语言用来序列化和反序列化数据的一个非常高效的解决方案。
本质上,serde提供了一个序列化层的概念。可以将任何支持的数据格式反序列化成中间格式,然后序列化成任何一种支持的数据格式。
设计
同其他语言通过反射来实现序列化方案不同,serde基于rust的trait系统来实现自己的序列化,每种数据结构通过实现serde的Serialize和Deserialize接口来实现序列化功能,这种实现方案可以有效避免反射的性能开销。rust编译器可以在很多场景下对序列化进行高度优化,甚至可以达到一个资深工程师手写序列化代码的性能。
支持的数据格式
这里列举一下目前serde社区已经实现的一些数据格式。
- json
- bincode
- CBOR
- YAML
- MessagePack
- TOML
- Pickle
- RON
- BSON
- Avro
- Hjson
- JSON5
- URL
- Envy
- Envy Store
数据结构
serde支持以下数据类型的序列化和反序列化,包括(String,&str,usize,Vec,HashMap<K,V>)。此外,serde还提供derive macro来为你自己定义的数据类型提供序列化和反序列化的实现。下面给出dervie macro的demo code。
#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;
#[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);
}
serde数据模型
serde数据模型就是一组数据结构和数据格式转换的api,你可以理解为serde的类型系统。
serde序列化的部分定义在Serializer的trait里。反序列化的部分定义在 Deserializer的trait里。Serde提供了一种方法,将任何Rust的数据类型映射成29种可能的类型。 Serializer trait的每一种方法都对应数据模型的每一种类型。
当将一个数据结构序列化成某一种数据格式时,该数据结构里Serializer的实现将数据结构通过Serializer方法精确的映射成Serde数据模型。而Serializer自己的实现再将Serde数据模型映射成输出的数据格式。
当从某一种数据格式反序列化成rust数据结构时,Deserializer自己的实现会把数据格式映射成Serde数据模型,再通过数据结构里Deserializer的实现,将Serde数据模型通过Visitor实现映射成rust数据结构。
serde类型系统
serde数据模型是rust类型系统的一个简化版本。它包括以下29种类型。
bool
i8, i16, i32, i64, i128
u8, u16, u32, u64, u128
f32, f64
char
string
bytearray
option
uint
uint_struct
uint_variant0
newtype_struct
newtype_variant
seq
tuple
tuple_struct
tuple_variant
map
struct
struct_variant
数据模型映射
在很多场景下, 把rust数据结构映射成serde数据模型是非常快速的。例如rust的bool类型映射成serde的bool类型,rust的tuple struct Rgb(u8, u8, u8)映射成serde的tuple struct结构。
Serialize和Deserialize trait可以将rust数据结构和serde数据模型快速映射起来。
举个栗子,考虑一下Rust的std::ffi::OsString类型,这个类型表示一个平台相关的字符串。在Unix系统上,他表示非零字节。 在windows系统上,他表示非零16位值。
我们可以很自然的想到将OsString映射成serde的以下两种类型。
作为serde字符串类型。 但里面是存在坑的。 因为OsString是非零数据,但serde字符串是utf8展示的, 允许字符串里存在零字节。这里在转换的时候会遇到问题。
作为serde字节数组类型。 这里没有作为serde字符串类型的坑。但是存在新的坑, 就是如果我们在Unix下序列化OsString类型,然后在windows下反序列化。因为这两个平台对字符串的定义不一致, 所以在这个转换中就会出现错误, 我们会得到一个不正常的反序列化之后的字符串。
所以大家看,做一个序列化和反序列化的方案其实不是那么容易的。好在我们还可以用一种方式来实现这个目的,那就是不要把OsString类型看做是一个字符串或者是一个字节数组。 我们还可以把它看成一个枚举。我们可以用如下的类型来定义它,哪怕跟每个平台的定义都不匹配。
enum OsString {
Unix(Vec<u8>),
Windows(Vec<u16>),
// and other platforms
}
映射到serde数据类型的方法灵活性是非常高的,在实现Serialize和Deserialize的过程中,一定要注意场景的上下文,根据场景选择最合适的方案来做。
使用derive
为了方便实现你自己创建的数据结构的序列化功能,serde提供了一个derive macro来自动生成你的数据结构的Serialize和Deserialize trait的实现代码。让你定义的数据结构通过serde数据模型方便的表达出来。
你只需要在你代码里通过添加一行#[derive(Serialize,Deserialize)] 。serde就会自动生成这些实现代码。
此功能基于rust的#[derive]范式来实现,类似于你通过derive自动实现系统内置的Clone,Copy,Debug和其他的一些trait。他能够给绝大多数数据结构和枚举自动生成trait实现代码。极少数情况下,面对一些非常复杂的数据结构,你可能需要手工去实现这些代码。
版权声明
本文为[许野平]所创,转载请带上原文链接,感谢
https://yeping.blog.csdn.net/article/details/124188340
边栏推荐
- [leetcode 59] spiral matrix II
- Class loading and classloader understanding
- Addition, deletion, query and modification of data
- How to use comparative learning to do unsupervised - [cvpr22] training & [eccv20] image translation
- Illustrate the significance of hashcode
- Viewer: introduce MySQL date function
- Comparative study paper - [Moco, cvpr2020] momentum contract for unsupervised visual representation learning
- Fundamentals of SQL: first knowledge of database and SQL - installation and basic introduction - Alibaba cloud Tianchi
- Practical operation - Nacos installation and configuration
- 4. Print form
猜你喜欢
Chapter 4 of line generation - linear correlation of vector systems
[leetcode 202] happy number
A general U-shaped transformer for image restoration
Export of data
Linear algebra Chapter 2 - matrices and their operations
自動控制(韓敏版)
Preparedstatement prevents SQL injection
Illustrate the significance of hashcode
[leetcode 401] binary Watch
Addition, deletion, modification and query of MySQL table
随机推荐
PyTorch笔记——通过搭建ResNet熟悉网络搭建方式(完整代码)
JDBC tool class encapsulation
MySQL advanced query
自動控制(韓敏版)
Calculation (enter the calculation formula to get the result)
Common sense of thread pool
Fact final variable and final variable
Algèbre linéaire chapitre 1 - déterminants
The bottom implementation principle of thread - static agent mode
[leetcode 290] word rules
檢測技術與原理
7.Domino piling
Sakura substring thinking
[leetcode 67] sum of two binary numbers
Use of multithreaded executors
3. Continuous integer
String notes
Failure to deliver XID in Seata distributed transaction project
程序設計訓練
LockSupport. Park and unpark, wait and notify