实现 Serialize

Serialize trait 如下所示:

use serde::Serializer;

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

fn main() {}

这个方法的作用是取出你的类型 (&self),通过在给定的 Serializer 上调用恰当的一个方法来映射它到 Serde 数据模型

在大多数情况下,Serde的派生能够为你的 crate 中定义的结构体和枚举生成适当的 Serialize实现。如果你需要自定义某种类型的序列化行为,而派生不支持,你可以自己实现 Serialize

序列化基本类型

作为最简单的示例,这里是内置的 i32Serialize 实现。

use std::os::raw::c_int as ActualI32;

use serde::{Serialize, Serializer};

#[allow(dead_code, non_camel_case_types)]
struct i32;

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

impl Serialize for i32 {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        impl Serialize2 for ActualI32 {
            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
            where
                S: Serializer,
            {
        serializer.serialize_i32(*self)
            }
        }

        _ = serializer;
        unimplemented!()
    }
}

fn main() {}

Serde 为所有 Rust 的 基本类型 提供了这样的实现,因此你无需自己实现它们,但是 serialize_i32 和类似方法可能在你的类型需要以原始形式表示时很有用。例如,你可以 将类似 C 的 enum 序列化为基本类型的数字

序列化 sequence 或 map

复合类型遵循初始化(init),元素(elements),结束(end)的三步过程。

use std::marker::PhantomData;

struct Vec<T>(PhantomData<T>);

impl<T> Vec<T> {
    fn len(&self) -> usize {
        unimplemented!()
    }
}

impl<'a, T> IntoIterator for &'a Vec<T> {
    type Item = &'a T;
    type IntoIter = Box<dyn Iterator<Item = &'a T>>;

    fn into_iter(self) -> Self::IntoIter {
        unimplemented!()
    }
}

struct MyMap<K, V>(PhantomData<K>, PhantomData<V>);

impl<K, V> MyMap<K, V> {
    fn len(&self) -> usize {
        unimplemented!()
    }
}

impl<'a, K, V> IntoIterator for &'a MyMap<K, V> {
    type Item = (&'a K, &'a V);
    type IntoIter = Box<dyn Iterator<Item = (&'a K, &'a V)>>;

    fn into_iter(self) -> Self::IntoIter {
        unimplemented!()
    }
}

use serde::ser::{Serialize, Serializer, SerializeSeq, SerializeMap};

impl<T> Serialize for Vec<T>
where
    T: Serialize,
{
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut seq = serializer.serialize_seq(Some(self.len()))?;
        for e in self {
            seq.serialize_element(e)?;
        }
        seq.end()
    }
}

impl<K, V> Serialize for MyMap<K, V>
where
    K: Serialize,
    V: Serialize,
{
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut map = serializer.serialize_map(Some(self.len()))?;
        for (k, v) in self {
            map.serialize_entry(k, v)?;
        }
        map.end()
    }
}

fn main() {}

序列化 tuple

serialize_tuple 方法与 serialize_seq 非常相似。Serde 所做的区别是 serialize_tuple 适用于序列,其长度不需要序列化,因为在反序列化时会知道长度。通常的示例是 Rust 的 tuplesarrays。在非自描述格式中,Vec<T> 需要以其长度序列化,以便能够将 Vec<T> 再次反序列化。但是 [T; 16] 可以使用 serialize_tuple 进行序列化,因为长度将在反序列化时知道,而无需查看序列化的 bytes。

序列化 struct

Serde 区分四种类型的结构体。普通结构体元组结构体 遵循初始化,元素,结束的三步过程,就像 sequence 或 map 一样。 新类型结构体单元结构体 更像基本类型。

#![allow(dead_code)]

// 一个普通结构体。使用三步过程:
//   1. serialize_struct
//   2. serialize_field
//   3. end
struct Color {
    r: u8,
    g: u8,
    b: u8,
}

// 一个元组结构体。使用三步过程:
//   1. serialize_tuple_struct
//   2. serialize_field
//   3. end
struct Point2D(f64, f64);

// 一个新类型结构体。使用 serialize_newtype_struct。
struct Inches(u64);

// 一个单元结构体。使用 serialize_unit_struct。
struct Instance;

fn main() {}

在某些格式中,包括 JSON,struct 和 map 可能看起来相似。Serde 的区别在于 struct 具有在编译时为常量的字符串键,并且这些键在不查看序列化数据的情况下是已知的。这个条件使得某些数据格式能够比 map 更高效和紧凑地处理 struct。

数据格式鼓励将新类型结构体视为内部值的不重要的外壳,只序列化内部值。例如,参见JSON 对新类型结构体的处理

#![allow(dead_code)]

use serde::ser::{Serialize, Serializer, SerializeStruct};

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,
    {
        // 3 是结构体中字段的数量。
        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()
    }
}

fn main() {}

序列化 enum

序列化 enum variants 与序列化 structs 非常相似。

#[allow(dead_code)]
enum E {
    // 使用三步过程:
    //   1. serialize_struct_variant
    //   2. serialize_field
    //   3. end
    Color { r: u8, g: u8, b: u8 },

    // 使用三步过程:
    //   1. serialize_tuple_variant
    //   2. serialize_field
    //   3. end
    Point2D(f64, f64),

    // 使用 serialize_newtype_variant。
    Inches(u64),

    // 使用 serialize_unit_variant。
    Instance,
}

fn main() {}

其他特殊情况

有两个更特殊的情况,属于 Serializer trait 的一部分。

有一个方法 serialize_bytes,用于序列化 &[u8]。有些格式将 bytes 视为 seq,但有些格式能够更紧凑地序列化 bytes。目前,Serde 在 Serialize 实现中不使用 serialize_bytes 用于 &[u8]Vec<u8>,但一旦specialization 在稳定的 Rust 中出现,我们将开始使用它。目前可以使用 serde_bytes crate 来使得能够通过 serialize_bytes 高效处理 &[u8]Vec<u8>

最后,serialize_someserialize_none 对应于 Option::SomeOption::None。用户对 Option 枚举的期望通常与其他枚举不同。Serde JSON 将 Option::None 序列化为 null,将 Option::Some 仅序列化为包含的值。