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?