Custom deserialize of url encoded JSON string

I am working on a fork of serde_urlencoded where nested struct values are serialized as a percent-encoded JSON string, a nested struct is deserialized below.

fn deserialize_struct<V>(
    self,
    _name: &'static str,
    _fields: &'static [&'static str],
    visitor: V,
) -> Result<V::Value, Self::Error>
where
    V: de::Visitor<'de>,
{
    // `raw_json` is the json string such as "{"key":"string", "array": [0,1,2]}"
    let map = serde_json::from_str::<serde_json::Value>(&raw_json)
        .map_err(|e| Error::custom(e.to_string()))?;

    let map_iter = map
        .as_object()
        .ok_or_else(|| Error::custom("must deserialize to a json object"))?
        .to_owned()
        .into_iter();

    visitor.visit_map(JsonDeserialize {
        map: map_iter,
        current: None,
    })
}

// The MapAccess impl
impl<'de, I> de::MapAccess<'de> for JsonDeserialize<I>
where
    I: Iterator<Item = (String, Value)>,
{
    type Error = Error;

    fn next_key_seed<K>(
        &mut self,
        seed: K,
    ) -> Result<Option<K::Value>, Self::Error>
    where
        K: de::DeserializeSeed<'de>,
    {
        if let Some((k, val)) = self.map.next() {
            self.current = Some(val);
            // `Part` deserializes the primative types
            seed.deserialize(Part(k.into(), None)).map(Some)
        } else {
            Ok(None)
        }
    }

    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
    where
        V: de::DeserializeSeed<'de>,
    {
        if let Some(val) = self.current.take() {
            let value = match val {
                Value::String(string) => string,
                Value::Number(num) => num.to_string(),
                Value::Object(_map) => {
                    return Err(Error::custom("multiple levels of nesting"))
                }
                Value::Array(vec) => {
                    return seed.deserialize(Part(
                        Cow::Borrowed(""),
                        Some(
                            vec.into_iter()
                                .map(|v| Cow::Owned(v.to_string()))
                                .collect(),
                        ),
                    ))
                }
                Value::Bool(b) => b.to_string(),
                Value::Null => String::default(),
            };
            // `Part` deserializes the primative types
            seed.deserialize(Part(value.into(), None))
        } else {
            Err(Error::custom("expected value"))
        }
    }
}

My question, is there a way to have Deserializer::deserialize_struct return the value returned from serde_json::from_str::<?Type?>(&raw_json), basically is there a way to name the type?

So here is what I came up with, this is inside of a impl Deserializer<'de> for PartDeserializer block

fn deserialize_struct<V>(
    self,
    name: &'static str,
    fields: &'static [&'static str],
    visitor: V,
) -> Result<V::Value, Self::Error>
where
    V: de::Visitor<'de>,
{
    let pairs = self
        .1
        .ok_or_else(|| Error::custom("percent decoding may have failed"))?;

    let raw_json = pairs
        .get(0)
        .ok_or_else(|| Error::custom("no value found for nested struct"))?;

    let mut de =
        serde_json::de::Deserializer::from_reader(raw_json.as_bytes());
    de.deserialize_struct(name, fields, visitor)
        .map_err(|e| Error::custom(e.to_string()))
}

using serde_json's internal Deserializer impl and just passing it along.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.