震惊!!rust中序列化还能这么玩

218 阅读5分钟

我们这章带大家实现Desialize,接着我们之前讲的继续我们的serde之旅。

实现Deserialize

Deserialize trait如下所示:

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

这个方法的作用是通过为Deserializer 提供一个Visitor,将类型映射到Serde数据类型,然后由Deserializer 驱动 Visitor 来构建类型的实例。

在大多数情况下,Serde的derive能够为你的crate中定义的struct和enum生成适当的Deserialize实现。如果你需要对某种类型的序列化为进行自定义,而派生不支持该行为,可以自己实现Deserialize。实现Deserialize对于类型而言比实现Serialize更加复杂。

Deserializer trait 支持两种入口样式,从而实现不同种类的反序列化。

  • deserialize_any方法。述像JSON 这样的自描述数据格式能够查看序列化数据并判断其代表的内容。例如,JSON 反序列化器可能看到一个左花括号 ({) 并知道它看到的是一个 map。如果数据格式支持 Deserializer::deserialize_any,它将根据 input 中判断的类型来驱动 Visitor。JSON 在反序列化 serde_json::Value 时使用了这种方法,它是能够表示任何 JSON 文档的 enum。不需要知道 JSON 文档中的内容是什么,我们也可以通过 Deserializer::deserialize_any 将其反序列化为 serde_json::Value。
  • 其他各种 deserialize_* 方法。非自描述格式例如 Postcard 需要告诉输入中包含的是什么内容才能对其进行反序列化。deserialize_* 方法是为反序列器提供关于如何解释下一个输入片段的提示。非自描述格式无法对类似serde_json::Value 这样依赖 Deserializer::deserialize_any 的内容进行反序列化。

在实现 Deserialize 时,应避免依赖Deserializer::deserialize_any,除非需要反序列化器告诉您输入中的类型。要知道,依赖Deserializer::deserialize_any 意味着您的数据类型只能从自描述格式中反序列化,排除了 Postcard 等许多其他格式。

下面我们看看Visitor trait

Visitor trait

Visitor是由Deserialize实例化冰传递给Deserializer的。然后,Deserializer会调用Visitor上的方法来构造所需要的类型。

我们来看Visitor示例,能够从各种类型中反序列化基本的i32。

use std::fmt;

use serde::de::{self, Visitor};

struct I32Visitor;

impl<'de> Visitor<'defor I32Visitor {
    type Value = i32;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("an integer between -2^31 and 2^31")
    }

    fn visit_i8<E>(self, value: i8-> Result<Self::Value, E>
    where
        E: de::Error,
    {
        Ok(i32::from(value))
    }

    fn visit_i32<E>(self, value: i32-> Result<Self::Value, E>
    where
        E: de::Error,
    {
        Ok(value)
    }

    fn visit_i64<E>(self, value: i64-> Result<Self::Value, E>
    where
        E: de::Error,
    {
        use std::i32;
        if value >= i64::from(i32::MIN) && value <= i64::from(i32::MAX) {
            Ok(value as i32)
        } else {
            Err(E::custom(format!("i32 out of range: {}", value)))
        }
    }

    // 其他方法类似:
    //   - visit_i16
    //   - visit_u8
    //   - visit_u16
    //   - visit_u32
    //   - visit_u64
}

Visitor trait 还有许多没有为I32Visitor实现的方法。如果调用这些方法,将返回类型错误。例如,I32Visitor没有实现Visitor::visit_map,因此尝试在输入包含映射时反序列化一个i32 是一个类型错误。

序列化自定义map类型

use std::fmt;
use std::marker::PhantomData;

use serde::de::{Deserialize, Deserializer, Visitor, MapAccess};

// Visitor 是一个类型,其中包含 Deserializer 可以根据输入数据的内容驱动的方法。
//
// 在 map 的情况下,我们需要泛型类型参数 K 和 V 来正确设置输出类型,但不需要任何状态。
// 这是 Rust 中的 “零大小类型” 的一个例子。PhantomData
// 防止编译器因未使用的泛型类型参数而抱怨。
struct MyMapVisitor<K, V> {
    marker: PhantomData<fn() -> MyMap<K, V>>
}

impl<K, V> MyMapVisitor<K, V> {
    fn new() -> Self {
        MyMapVisitor {
            marker: PhantomData
        }
    }
}

// 这是Deserializers将驱动的特质。每种类型的数据都有一个与之对应的方法
// 我们的类型知道如何从中反序列化。这里有许多其他未在此处实现的方法,例如从整数或字符串反序列化。
// 默认情况下,这些方法将返回错误,这是有道理的,因为我们无法从整数或字符串反序列化MyMap。
impl<'de, K, V> Visitor<'defor MyMapVisitor<K, V>
where
    K: Deserialize<'de>,
    V: Deserialize<'de>,
{
    //我们的Visitor将生成的类型。
    type Value = MyMap<K, V>;

    //格式化一条消息,说明该 Visitor 希望接收哪些数据。
    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("一个非常特殊的 map")
    }

    // 从Deserializer提供的抽象“地图”中反序列化MyMap。MapAccess输入是Deserializer提供的回调,让我们可以看到地图中的每个条目。
    fn visit_map<M>(selfmut access: M) -> Result<Self::Value, M::Error>
    where
        M: MapAccess<'de>,
    {
        let mut map = MyMap::with_capacity(access.size_hint().unwrap_or(0));

        // 在输入中还有条目时,将它们添加到我们的地图中。
        while let Some((key, value)) = access.next_entry()? {
            map.insert(key, value);
        }

        Ok(map)
    }
}

// 这是告诉 Serde 如何反序列化 MyMap 的特质。
impl<'de, K, V> Deserialize<'defor MyMap<K, V>
where
    K: Deserialize<'de>,
    V: Deserialize<'de>,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        //实例化我们的 Visitor,并要求 Deserializer 在输入数据上驱动它,从而生成 MyMap 的实例。
        deserializer.deserialize_map(MyMapVisitor::new())
    }
}

反序列化strcut

struct Duration {
    secs: u64,
    nanos: u32,
}


use std::fmt;

use serde::de::{self, Deserialize, Deserializer, Visitor, SeqAccess, MapAccess};

impl<'de> Deserialize<'defor Duration {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        enum Field { Secs, Nanos }

        // This part could also be generated independently by:
        //
        //    #[derive(Deserialize)]
        //    #[serde(field_identifier, rename_all = "lowercase")]
        //    enum Field { Secs, Nanos }
        impl<'de> Deserialize<'defor Field {
            fn deserialize<D>(deserializer: D) -> Result<Field, D::Error>
            where
                D: Deserializer<'de>,
            {
                struct FieldVisitor;

                impl<'de> Visitor<'defor FieldVisitor {
                    type Value = Field;

                    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                        formatter.write_str("`secs` or `nanos`")
                    }

                    fn visit_str<E>(self, value: &str-> Result<Field, E>
                    where
                        E: de::Error,
                    {
                        match value {
                            "secs" => Ok(Field::Secs),
                            "nanos" => Ok(Field::Nanos),
                            _ => Err(de::Error::unknown_field(value, FIELDS)),
                        }
                    }
                }

                deserializer.deserialize_identifier(FieldVisitor)
            }
        }

        struct DurationVisitor;

        impl<'de> Visitor<'defor DurationVisitor {
            type Value = Duration;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("struct Duration")
            }

            fn visit_seq<V>(selfmut seq: V) -> Result<Duration, V::Error>
            where
                V: SeqAccess<'de>,
            {
                let secs = seq.next_element()?
                    .ok_or_else(|| de::Error::invalid_length(0, &self))?;
                let nanos = seq.next_element()?
                    .ok_or_else(|| de::Error::invalid_length(1, &self))?;
                Ok(Duration::new(secs, nanos))
            }

            fn visit_map<V>(selfmut map: V) -> Result<Duration, V::Error>
            where
                V: MapAccess<'de>,
            {
                let mut secs = None;
                let mut nanos = None;
                while let Some(key) = map.next_key()? {
                    match key {
                        Field::Secs => {
                            if secs.is_some() {
                                return Err(de::Error::duplicate_field("secs"));
                            }
                            secs = Some(map.next_value()?);
                        }
                        Field::Nanos => {
                            if nanos.is_some() {
                                return Err(de::Error::duplicate_field("nanos"));
                            }
                            nanos = Some(map.next_value()?);
                        }
                    }
                }
                let secs = secs.ok_or_else(|| de::Error::missing_field("secs"))?;
                let nanos = nanos.ok_or_else(|| de::Error::missing_field("nanos"))?;
                Ok(Duration::new(secs, nanos))
            }
        }

        const FIELDS: &'static [&'static str] = &["secs""nanos"];
        deserializer.deserialize_struct("Duration", FIELDS, DurationVisitor)
    }
}

最后希望大家多关注我的公众号哈:花说编程