How to deserialize a sequence into a custom type with Serde's SeqDeserializer?

Viewed 1234

I'm trying to write a custom serializer and derializer for a type which is uncomplicated but doesn't have a natural JSON representation.

pub type ArrayKey = [i16; 5];

pub struct ArrayKeyedMap {
    the_map: HashMap<ArrayKey, u32>
}

The HashMap, having array keys, can't be represented as a JSON map (which must have string keys). So I want to serialize it as a sequence of pairs. The documentation for Serialization of a sequence is very clear, and the following works:

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

This serializes as e.g. [[1,2,3,4,5], 1, [5,4,3,2,1], 2]. The documentation for deserialization of a sequence is not so easy to follow and I can't make the leap between the Visitor and how to retrieve data from a SeqDeserializer. I'm not sure if I'm meant to pass something in, or get a returned value, or something else.

impl<'de> Deserialize<'de> for ArrayKeyedMap
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where
            D: Deserializer<'de>,
    {
        deserializer.deserialize_seq(SeqDeserializer::new // not sure how to proceed
    }
}

How do I deserialize this back into the map with array keys?

1 Answers

Not sure if this is the perfect answer, but this is what worked. The Visitor needs to be implemented as a separate struct, which is a little more complex as the serializer. But the docs warn of this!


impl ArrayKeyedMap {
    pub fn new() -> ArrayKeyedMap {
        ArrayKeyedMap {
            the_map: HashMap::new(),
        }
    }
}

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

struct ArrayKeyedMapDeserializer;

impl<'de> Visitor<'de> for ArrayKeyedMapDeserializer {
    type Value = ArrayKeyedMap;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("ArrayKeyedMap key value sequence.")
    }

    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
    where
        A: SeqAccess<'de>,
    {
        let mut new_obj = ArrayKeyedMap::new();
        while let Some(key) = seq.next_element()? {
            if let Some(value) = seq.next_element()? {
                new_obj.the_map.insert(key, value);
            } else {
                return Err(de::Error::custom(format!(
                    "Didn't find the right sequence of values in ArrayKeyedMap."
                )));
            }
        }

        Ok(new_obj)
    }
}

impl<'de> Deserialize<'de> for ArrayKeyedMap {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_seq(ArrayKeyedMapDeserializer)
    }
}
Related