Serde 序列化框架

Rust 数据序列化的黄金标准

🦀 源码深度解读 | 基于 serde v1.0

2026.03.08

📚 内容概览

第一部分:基础篇

  • Serde 简介与生态系统
  • 核心架构设计
  • 数据模型(29种类型)

第二部分:序列化篇

  • Serialize Trait 详解
  • Serializer Trait 实现
  • 派生宏工作原理

第三部分:反序列化篇

  • Deserialize Trait 详解
  • Deserializer Trait 实现
  • Visitor 模式深度解析

第四部分:实战篇

  • 高级特性与属性配置
  • 自定义格式实现
  • 性能优化技巧

🦀 Serde 是什么?

Serde 是 Rust 生态中用于序列化反序列化数据的框架。

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
struct User {
    name: String,
    age: u32,
    active: bool,
}

// 序列化
let user = User { name: "Alice".into(), age: 30, active: true };
let json = serde_json::to_string(&user)?;  // {"name":"Alice","age":30,"active":true}

// 反序列化
let decoded: User = serde_json::from_str(&json)?;

为什么选择 Serde?

10B+
累计下载量
30+
数据格式支持
0
运行时依赖
2x
比其他框架快

零成本抽象

编译期生成代码,无运行时开销

🔧 高度可扩展

支持自定义序列化逻辑和格式

🎯 类型安全

充分利用 Rust 类型系统保证安全

📦 零拷贝

支持借用输入数据的反序列化

🌐 Serde 生态系统

Rust 数据结构
⬇️
serde_core
serde_derive
⬇️
serde_json
serde_yaml
postcard
bincode

设计哲学:数据结构与数据格式完全解耦,一个 Serialize 实现可用于所有格式!

第一部分:核心架构

📊 Serde 数据模型(29种类型)

类别 类型 Rust 示例
原始类型 (14) bool, i8-i128, u8-u128, f32, f64, char true, 42i32, 3.14f64, '🦀'
字符串 string &str, String
字节数组 byte array &[u8], Vec<u8>
Option none, some Option<T>
Unit unit, unit_struct, unit_variant (), struct Foo;
Newtype newtype_struct, newtype_variant struct Millimeters(u8);
序列 seq, tuple, tuple_struct, tuple_variant Vec<T>, (A, B, C)
映射 map, struct, struct_variant HashMap<K,V>, struct S { }

📤 Serialize Trait

pub trait Serialize {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer;
}

核心职责:将 Rust 数据结构转换为 Serializer 能理解的抽象操作序列。

Rust 数据
Serialize::serialize
Serializer 方法调用
格式化输出

🔧 Serializer Trait

pub trait Serializer: Sized {
    type Ok;
    type Error: Error;
    
    // 原始类型
    fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error>;
    fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error>;
    fn serialize_str(self, value: &str) -> Result<Self::Ok, Self::Error>;
    
    // 复合类型
    fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error>;
    fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error>;
    fn serialize_struct(
        self,
        name: &'static str,
        len: usize,
    ) -> Result<Self::SerializeStruct, Self::Error>;
    
    // ... 更多方法
}

🔄 序列化流程示例

struct Point { x: i32, y: i32 }

impl Serialize for Point {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where S: Serializer {
        // 1. 开始序列化结构体
        let mut s = serializer.serialize_struct("Point", 2)?;
        // 2. 序列化字段
        s.serialize_field("x", &self.x)?;
        s.serialize_field("y", &self.y)?;
        // 3. 结束
        s.end()
    }
}

JSON 输出:{"x":10,"y":20}

Bincode 输出:[10, 0, 0, 0, 20, 0, 0, 0](二进制)

📥 Deserialize Trait

pub trait Deserialize<'de>: Sized {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>;
}

生命周期 'de:表示反序列化器可能借用的数据的生命周期,支持零拷贝反序列化。

格式化输入
Deserializer::deserialize_*
Visitor 回调
Rust 数据

🔧 Deserializer Trait

pub trait Deserializer<'de>: Sized {
    type Error: Error;
    
    // 反序列化任何类型(用于自描述格式如 JSON)
    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where V: Visitor<'de>;
    
    // 特定类型提示(用于非自描述格式如 Postcard)
    fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where V: Visitor<'de>;
    
    fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where V: Visitor<'de>;
    
    fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where V: Visitor<'de>;
    
    fn deserialize_struct<V>(
        self,
        name: &'static str,
        fields: &'static [&'static str],
        visitor: V,
    ) -> Result<V::Value, Self::Error>
    where V: Visitor<'de>;
}

🔄 反序列化流程示例

impl<'de> Deserialize<'de> for Point {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where D: Deserializer<'de> {
        // 1. 定义字段
        enum Field { X, Y }
        
        // 2. 定义 Visitor
        struct PointVisitor;
        impl<'de> Visitor<'de> for PointVisitor {
            type Value = Point;
            
            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
                f.write_str("struct Point")
            }
            
            fn visit_map<M>(self, mut map: M) -> Result<Point, M::Error>
            where M: MapAccess<'de> {
                let mut x = None;
                let mut y = None;
                while let Some(key) = map.next_key()? {
                    match key {
                        Field::X => { x = Some(map.next_value()?); }
                        Field::Y => { y = Some(map.next_value()?); }
                    }
                }
                Ok(Point { x: x.unwrap(), y: y.unwrap() })
            }
        }
        
        // 3. 调用 deserializer
        deserializer.deserialize_struct("Point", FIELDS, PointVisitor)
    }
}

Visitor 模式

🎯 Visitor Trait 定义

pub trait Visitor<'de>: Sized {
    type Value;
    
    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result;
    
    // 原始类型访问
    fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
    where E: Error { ... }
    
    fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E>
    where E: Error { ... }
    
    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
    where E: Error { ... }
    
    // 复合类型访问
    fn visit_seq<A>(self, seq: A) -> Result<Self::Value, A::Error>
    where A: SeqAccess<'de> { ... }
    
    fn visit_map<A>(self, map: A) -> Result<Self::Value, A::Error>
    where A: MapAccess<'de> { ... }
}

设计模式:Visitor 是经典的访问者模式,Deserializer 遍历数据并调用 Visitor 的相应方法。

派生宏原理

🔬 serde_derive 工作原理

// 输入
#[derive(Serialize, Deserialize)]
struct User {
    name: String,
    age: u32,
}

// 生成的代码(简化版)
impl Serialize for User {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where S: Serializer {
        let mut __serde_state = serializer.serialize_struct("User", 2)?;
        SerializeStruct::serialize_field(&mut __serde_state, "name", &self.name)?;
        SerializeStruct::serialize_field(&mut __serde_state, "age", &self.age)?;
        SerializeStruct::end(__serde_state)
    }
}

编译期生成:所有代码在编译时生成,零运行时开销!

📤 序列化派生详解

源码路径:serde_derive/src/ser.rs

pub fn expand_derive_serialize(input: &mut syn::DeriveInput) -> syn::Result<TokenStream> {
    let ctxt = Ctxt::new();
    let cont = Container::from_ast(&ctxt, input, Derive::Serialize, &private.ident());
    
    let ident = &cont.ident;
    let params = Parameters::new(&cont);
    let body = serialize_body(&cont, ¶ms);
    
    quote! {
        impl #impl_generics _serde::Serialize for #ident #ty_generics #where_clause {
            fn serialize<__S>(&self, __serializer: __S) -> _serde::Result<__S::Ok, __S::Error>
            where __S: _serde::Serializer {
                #body
            }
        }
    }
}

📥 反序列化派生详解

源码路径:serde_derive/src/de.rs

pub fn expand_derive_deserialize(input: &mut syn::DeriveInput) -> syn::Result<TokenStream> {
    let ctxt = Ctxt::new();
    let cont = Container::from_ast(&ctxt, input, Derive::Deserialize, &private.ident());
    
    let params = Parameters::new(&cont);
    let body = deserialize_body(&cont, ¶ms);
    let delife = params.borrowed.de_lifetime();
    
    quote! {
        impl #de_impl_generics _serde::Deserialize<#delife> 
            for #ident #ty_generics #where_clause {
            fn deserialize<__D>(__deserializer: __D) -> _serde::Result<Self, __D::Error>
            where __D: _serde::Deserializer<#delife> {
                #body
            }
        }
    }
}

⚠️ 错误处理

pub trait Error: Sized + StdError {
    fn custom<T>(msg: T) -> Self where T: Display;
    
    fn invalid_type(unexp: Unexpected, exp: &dyn Expected) -> Self;
    fn invalid_value(unexp: Unexpected, exp: &dyn Expected) -> Self;
    fn invalid_length(len: usize, exp: &dyn Expected) -> Self;
    fn unknown_variant(variant: &str, expected: &'static [&'static str]) -> Self;
    fn unknown_field(field: &str, expected: &'static [&'static str]) -> Self;
    fn missing_field(field: &'static str) -> Self;
    fn duplicate_field(field: &'static str) -> Self;
}

pub enum Unexpected<'a> {
    Bool(bool),
    Unsigned(u64),
    Signed(i64),
    Float(f64),
    Str(&'a str),
    Bytes(&'a [u8]),
    Unit, Option, Seq, Map, Enum, ...
}

生命周期详解

// 零拷贝反序列化
#[derive(Deserialize)]
struct BorrowedData<'a> {
    // 借用输入字符串,无需分配新内存
    name: &'a str,
    bytes: &'a [u8],
}

// 反序列化时数据借用自输入
let input = r#"{"name":"hello","bytes":[1,2,3]}"#;
let data: BorrowedData = serde_json::from_str(input)?;
// data.name 直接指向 input 中的 "hello"

性能提升:零拷贝可避免大量内存分配,特别适合大数据量场景。

🚀 零拷贝反序列化原理

输入: {"name":"test"}
// 普通反序列化 - 需要分配
struct Owned {
    name: String,  // 分配新内存存储 "test"
}

// 零拷贝反序列化 - 直接借用
struct Borrowed<'a> {
    name: &'a str,  // 指向原始输入中的 "test"
}

// serde_json 内部处理
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> {
    // v 是从输入字符串切片得到的引用
    Ok(Borrowed { name: v })
}

属性配置

✏️ 重命名属性

// 字段重命名
#[derive(Serialize, Deserialize)]
struct User {
    #[serde(rename = "fullName")]
    full_name: String,
    
    #[serde(rename = "createdAt")]
    created_at: DateTime,
}

// 批量重命名规则
#[serde(rename_all = "camelCase")]
struct ApiRequest {
    user_id: String,     // → userId
    created_at: i64,     // → createdAt
}

#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
enum Status {
    InProgress,  // → IN_PROGRESS
    Completed,   // → COMPLETED
}

支持的重命名规则:lowercase, UPPECASE, PascalCase, camelCase, snake_case, SCREAMING_SNAKE_CASE, kebab-case, SCREAMING-KEBAB-CASE

⏭️ 跳过字段

#[derive(Serialize, Deserialize)]
struct User {
    name: String,
    
    // 序列化时跳过
    #[serde(skip_serializing)]
    password: String,
    
    // 反序列化时跳过
    #[serde(skip_deserializing)]
    internal_id: u64,
    
    // 两者都跳过
    #[serde(skip)]
    cache: HashMap<String, String>,
    
    // 条件跳过
    #[serde(skip_serializing_if = "Option::is_none")]
    optional_field: Option<String>,
}

🔧 默认值

#[derive(Deserialize)]
struct Config {
    // 使用 Default trait
    #[serde(default)]
    port: u16,  // 默认 0
    
    // 自定义默认值函数
    #[serde(default = "default_host")]
    host: String,
    
    // 嵌套结构默认值
    #[serde(default)]
    options: Options,
}

fn default_host() -> String {
    "localhost".to_string()
}

// 整个结构体使用默认值
#[serde(default)]
struct Settings {
    timeout: u64,
    retries: u32,
}

🎨 自定义序列化

// 使用 with 属性
#[derive(Serialize, Deserialize)]
struct Event {
    #[serde(with = "my_datetime_format")]
    timestamp: DateTime,
}

mod my_datetime_format {
    use serde::{Serialize, Deserialize, Serializer, Deserializer};
    
    pub fn serialize<S>(date: &DateTime, serializer: S) -> Result<S::Ok, S::Error>
    where S: Serializer {
        serializer.serialize_str(&date.to_rfc3339())
    }
    
    pub fn deserialize<'de, D>(deserializer: D) -> Result<DateTime, D::Error>
    where D: Deserializer<'de> {
        let s = String::deserialize(deserializer)?;
        DateTime::parse_from_rfc3339(&s)
            .map_err(serde::de::Error::custom)
    }
}

📊 Flatten 属性

#[derive(Serialize, Deserialize)]
struct Pagination {
    page: u32,
    per_page: u32,
}

#[derive(Serialize, Deserialize)]
struct ApiResponse {
    data: Vec<Item>,
    
    // 将 Pagination 字段展开到顶层
    #[serde(flatten)]
    pagination: Pagination,
}

// 输出: {"data":[...], "page":1, "per_page":10}
// 而不是: {"data":[...], "pagination":{"page":1, "per_page":10}}

用途:组合多个结构体、处理额外字段、实现 trait 对象序列化。

🏷️ Enum 处理

enum Message {
    Request { id: String, method: String },
    Response { id: String, result: Value },
}

// 默认外部标签格式
{"Request": {"id": "1", "method": "get"}}

// 内部标签
#[serde(tag = "type")]
enum Message {
    Request { id: String, method: String },
    // → {"type": "Request", "id": "1", "method": "get"}
}

// 相邻标签
#[serde(tag = "type", content = "data")]
enum Message {
    Request { id: String, method: String },
    // → {"type": "Request", "data": {"id": "1", "method": "get"}}
}

// 无标签
#[serde(untagged)]
enum Value {
    String(String),
    Number(i64),
    // → 直接输出值,无类型标签
}

🏷️ Enum 标签策略对比

策略 属性 JSON 示例
外部标签 (默认) {"Variant":{...}}
内部标签 tag="type" {"type":"Variant",...}
相邻标签 tag+content {"type":"V","data":{...}}
无标签 untagged {...} 或 "value"

无标签风险:untagged 可能导致歧义,反序列化时按顺序尝试匹配。

serde_json 集成

📦 serde_json::Value

enum Value {
    Null,
    Bool(bool),
    Number(Number),
    String(String),
    Array(Vec<Value>),
    Object(Map<String, Value>),
}

// 动态解析 JSON
let v: Value = serde_json::from_str(r#"{"name":"test"}"#)?;
println!("{}", v["name"]);  // test

// 构建复杂 JSON
let json = json!({
    "name": "Alice",
    "age": 30,
    "hobbies": ["reading", "coding"],
    "address": {
        "city": "Beijing"
    }
});

📁 其他数据格式支持

文本格式

  • serde_json - JSON
  • serde_yaml - YAML
  • toml - TOML
  • serde_xml_rs - XML

二进制格式

  • bincode - 紧凑二进制
  • postcard - 嵌入式优化
  • serde_cbor - CBOR
  • rmp-serde - MessagePack

网络格式

  • serde_urlencoded - URL 编码
  • serde_qs - 查询字符串

特殊格式

  • serde_bytes - 高效字节处理
  • serde_repr - 整数枚举

性能优化技巧

// 1. 使用零拷贝
#[derive(Deserialize)]
struct FastData<'a> {
    #[serde(borrow)]
    data: &'a [u8],
}

// 2. 预分配缓冲区
let mut buffer = Vec::with_capacity(1024);
serde_json::to_writer(&mut buffer, &data)?;

// 3. 使用 from_reader 避免加载全部数据
let data: BigStruct = serde_json::from_reader(file)?;

// 4. 二进制格式更快
let bytes = bincode::serialize(&data)?;  // 比 JSON 快 3-5 倍

// 5. 跳过不需要的字段
#[derive(Deserialize)]
struct Partial {
    #[serde(flatten)]
    extra: IgnoredAny,  // 忽略所有额外字段
}

📊 性能基准

操作 serde_json bincode postcard
序列化 1MB 数据 2.5ms 0.8ms 0.5ms
反序列化 1MB 数据 3.2ms 1.0ms 0.7ms
输出大小 100% ~40% ~35%

结论:二进制格式在速度和大小上都优于文本格式,但 JSON 更通用。

🔧 自定义 Serializer

struct SimpleSerializer;

impl Serializer for SimpleSerializer {
    type Ok = String;
    type Error = Error;
    type SerializeSeq = Impossible<String, Error>;
    // ...

    fn serialize_bool(self, v: bool) -> Result<String, Error> {
        Ok(if v { "true".into() } else { "false".into() })
    }

    fn serialize_i32(self, v: i32) -> Result<String, Error> {
        Ok(v.to_string())
    }

    fn serialize_str(self, value: &str) -> Result<String, Error> {
        Ok(format!("\"{}\"", value))
    }
}

// 使用
let output = 42.serialize(SimpleSerializer)?;  // "42"

🔧 自定义 Deserializer

struct SimpleDeserializer<'a> {
    input: &'a str,
}

impl<'de> Deserializer<'de> for SimpleDeserializer<'de> {
    type Error = Error;

    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
    where V: Visitor<'de> {
        if self.input.starts_with('"') {
            visitor.visit_str(self.input.trim_matches('"'))
        } else if let Ok(n) = self.input.parse::<i64>() {
            visitor.visit_i64(n)
        } else {
            Err(Error::custom("unknown type"))
        }
    }
}

实战案例

🌐 实战:API 响应处理

#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
struct ApiResponse<T> {
    success: bool,
    #[serde(skip_serializing_if = "Option::is_none")]
    data: Option<T>,
    #[serde(skip_serializing_if = "Option::is_none")]
    error: Option<ApiError>,
    #[serde(with = "ts_milliseconds")]
    timestamp: DateTime<Utc>,
}

#[derive(Serialize, Deserialize)]
struct ApiError {
    code: u32,
    message: String,
    #[serde(skip_serializing_if = "Vec::is_empty")]
    details: Vec<String>,
}

📡 实战:二进制协议

#[derive(Serialize, Deserialize)]
#[repr(u8)]
enum PacketType {
    Handshake = 0x01,
    Data = 0x02,
    Ack = 0x03,
}

#[derive(Serialize, Deserialize)]
struct Packet {
    #[serde(rename = "type")]
    type_: PacketType,
    #[serde(with = "BigEndian")]
    length: u32,
    #[serde(skip_serializing_if = "Vec::is_empty")]
    payload: Vec<u8>,
}

// 使用 bincode 序列化
let packet = Packet { type_: PacketType::Data, length: 100, payload: vec![...] };
let bytes = bincode::serialize(&packet)?;

高级特性

🔌 远程类型(Remote Types)

// 为第三方类型实现 Serde
#[serde(remote = "DateTime")]
impl DateTimeSerde {
    #[serde(getter = "DateTime::timestamp")]
    fn timestamp(dt: &DateTime) -> i64 { dt.timestamp() }
    
    #[serde(getter = "DateTime::timestamp_millis")]
    fn timestamp_millis(dt: &DateTime) -> i64 { dt.timestamp_millis() }
}

#[derive(Deserialize)]
struct Event {
    #[serde(with = "DateTimeSerde")]
    created_at: DateTime,
}

📐 泛型支持

#[derive(Serialize, Deserialize)]
struct Container<T> {
    value: T,
    metadata: String,
}

// 自动生成正确的 trait bounds
// 等价于:
impl<T: Serialize> Serialize for Container<T> { ... }
impl<'de, T: Deserialize<'de>> Deserialize<'de> for Container<T> { ... }

// 自定义 bounds
#[serde(bound = "T: Serialize + Clone")]
struct StrictContainer<T> {
    value: T,
}

最佳实践

📦 结构设计

  • 使用 Option 表示可选字段
  • 避免过度嵌套
  • 为大型结构实现 Default

性能

  • 优先使用零拷贝
  • 考虑二进制格式
  • 预分配缓冲区

🔒 安全

  • 验证反序列化输入
  • 限制递归深度
  • 处理异常数据

🛠️ 可维护性

  • 文档化自定义格式
  • 版本控制策略
  • 向后兼容设计

⚠️ 常见陷阱

// ❌ 陷阱 1:忽略生命周期
struct Bad<'a> {
    data: &'a str,
}
let json = r#"{"data":"test"}"#.to_string();  // 移动!
let v: Bad = serde_json::from_str(&json)?;     // 编译错误

// ✅ 解决方案:使用 Cow 或 owned
#[derive(Deserialize)]
struct Good<'a> {
    #[serde(borrow)]
    data: Cow<'a, str>,
}

// ❌ 陷阱 2:未处理未知字段
// 默认会报错

// ✅ 解决方案
#[serde(deny_unknown_fields)]  // 显式拒绝
struct Strict { ... }

#[serde(flatten)]              // 忽略额外字段
extra: IgnoredAny,

🐛 调试技巧

// 1. 打印序列化结果
println!("{}", serde_json::to_string_pretty(&data)?);

// 2. 使用 #[serde(deny_unknown_fields)] 定位字段名问题

// 3. 自定义错误消息
#[serde(deny_unknown_fields, expecting = "a valid User object")]
struct User { ... }

// 4. 使用 serde_plain 调试
let s = serde_plain::to_string(&value)?;

// 5. 启用调试日志
RUST_LOG=serde=debug cargo run

// 6. 检查派生展开
cargo expand

⚖️ 与其他框架对比

特性 Serde protobuf cap'n proto
Schema 要求 ❌ 不需要 ✅ 需要 ✅ 需要
零拷贝 ✅ 支持 ✅ 原生
格式灵活性 ✅ 30+ ❌ 仅 protobuf ❌ 仅 cap'n
Rust 优先
跨语言 ⚠️ 有限

🔮 未来展望

Serde v2 计划

  • 更简洁的 API
  • 更好的错误消息
  • 改进的 async 支持
  • 更小的编译时间

社区发展

  • 更多数据格式支持
  • 与其他生态集成(Tokio, async-std)
  • IDE 支持改进

总结

🎯 核心要点

架构设计

  • 数据与格式解耦
  • Serialize/Serializer 分离
  • Visitor 模式驱动反序列化

性能特性

  • 编译期代码生成
  • 零成本抽象
  • 零拷贝反序列化

使用建议

  • 善用属性配置
  • 选择合适的格式
  • 遵循最佳实践

扩展能力

  • 自定义 Serializer/Deserializer
  • 远程类型支持
  • 丰富的生态系统

📚 参考资源

官方资源

推荐阅读

  • Serde 数据模型文档
  • Implementing a Serializer 教程
  • serde_derive 源码

感谢阅读!

Serde - 让 Rust 数据序列化变得简单高效

🦀 访问 serde.rs 了解更多