为 struct 手动实现 Deserialize
仅当派生无法完成任务时。
下面的 Deserialize
实现对应于以下结构体:
#[allow(dead_code)] struct Duration { secs: u64, nanos: u32, } fn main() {}
反序列化结构体比反序列化映射要复杂一些,以避免分配一个 String 来保存字段名称。而是有一 个Field
枚举,从 &str
中反序列化。
该实现支持数据格式中可能有两种表示结构体的方式:作为 seq,例如在 Postcard 中,或者作为 map,例如在 JSON 中。
use std::fmt; use serde::de::{self, Deserialize, Deserializer, Visitor, SeqAccess, MapAccess}; #[allow(dead_code)] struct Duration { secs: u64, nanos: u32, } impl Duration { fn new(_: u64, _: u32) -> Self { unimplemented!() } } impl<'de> Deserialize<'de> for 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<'de> for Field { fn deserialize<D>(deserializer: D) -> Result<Field, D::Error> where D: Deserializer<'de>, { struct FieldVisitor; impl<'de> Visitor<'de> for 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<'de> for DurationVisitor { type Value = Duration; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("struct Duration") } fn visit_seq<V>(self, mut 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>(self, mut 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) } } fn main() {}