Merge pull request #1135 from swlynch99/map-deserializer

Implement `Deserializer` for `Map<String, Value>` and `&Map<String, Value>`
This commit is contained in:
David Tolnay 2024-10-18 15:49:00 -07:00 committed by GitHub
commit b4954a9561
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 185 additions and 104 deletions

View File

@ -589,6 +589,22 @@ macro_rules! delegate_iterator {
} }
} }
impl<'de> de::IntoDeserializer<'de, crate::Error> for Map<String, Value> {
type Deserializer = Self;
fn into_deserializer(self) -> Self::Deserializer {
self
}
}
impl<'de> de::IntoDeserializer<'de, crate::Error> for &'de Map<String, Value> {
type Deserializer = Self;
fn into_deserializer(self) -> Self::Deserializer {
self
}
}
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
/// A view into a single entry in a map, which may either be vacant or occupied. /// A view into a single entry in a map, which may either be vacant or occupied.

View File

@ -203,21 +203,72 @@ where
} }
} }
fn visit_object<'de, V>(object: Map<String, Value>, visitor: V) -> Result<V::Value, Error> impl<'de> serde::Deserializer<'de> for Map<String, Value> {
where type Error = Error;
V: Visitor<'de>,
{ fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
let len = object.len(); where
let mut deserializer = MapDeserializer::new(object); V: Visitor<'de>,
let map = tri!(visitor.visit_map(&mut deserializer)); {
let remaining = deserializer.iter.len(); let len = self.len();
if remaining == 0 { let mut deserializer = MapDeserializer::new(self);
Ok(map) let map = tri!(visitor.visit_map(&mut deserializer));
} else { let remaining = deserializer.iter.len();
Err(serde::de::Error::invalid_length( if remaining == 0 {
len, Ok(map)
&"fewer elements in map", } else {
)) Err(serde::de::Error::invalid_length(
len,
&"fewer elements in map",
))
}
}
fn deserialize_enum<V>(
self,
_name: &'static str,
_variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
let mut iter = self.into_iter();
let (variant, value) = match iter.next() {
Some(v) => v,
None => {
return Err(serde::de::Error::invalid_value(
Unexpected::Map,
&"map with a single key",
));
}
};
// enums are encoded in json as maps with a single key:value pair
if iter.next().is_some() {
return Err(serde::de::Error::invalid_value(
Unexpected::Map,
&"map with a single key",
));
}
visitor.visit_enum(EnumDeserializer {
variant,
value: Some(value),
})
}
fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
drop(self);
visitor.visit_unit()
}
forward_to_deserialize_any! {
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
bytes byte_buf option unit unit_struct newtype_struct seq tuple
tuple_struct map struct identifier
} }
} }
@ -238,7 +289,7 @@ impl<'de> serde::Deserializer<'de> for Value {
#[cfg(not(any(feature = "std", feature = "alloc")))] #[cfg(not(any(feature = "std", feature = "alloc")))]
Value::String(_) => unreachable!(), Value::String(_) => unreachable!(),
Value::Array(v) => visit_array(v, visitor), Value::Array(v) => visit_array(v, visitor),
Value::Object(v) => visit_object(v, visitor), Value::Object(v) => v.deserialize_any(visitor),
} }
} }
@ -269,44 +320,24 @@ impl<'de> serde::Deserializer<'de> for Value {
#[inline] #[inline]
fn deserialize_enum<V>( fn deserialize_enum<V>(
self, self,
_name: &str, name: &'static str,
_variants: &'static [&'static str], variants: &'static [&'static str],
visitor: V, visitor: V,
) -> Result<V::Value, Error> ) -> Result<V::Value, Error>
where where
V: Visitor<'de>, V: Visitor<'de>,
{ {
let (variant, value) = match self { match self {
Value::Object(value) => { Value::Object(value) => value.deserialize_enum(name, variants, visitor),
let mut iter = value.into_iter(); Value::String(variant) => visitor.visit_enum(EnumDeserializer {
let (variant, value) = match iter.next() { variant,
Some(v) => v, value: None,
None => { }),
return Err(serde::de::Error::invalid_value( other => Err(serde::de::Error::invalid_type(
Unexpected::Map, other.unexpected(),
&"map with a single key", &"string or map",
)); )),
} }
};
// enums are encoded in json as maps with a single key:value pair
if iter.next().is_some() {
return Err(serde::de::Error::invalid_value(
Unexpected::Map,
&"map with a single key",
));
}
(variant, Some(value))
}
Value::String(variant) => (variant, None),
other => {
return Err(serde::de::Error::invalid_type(
other.unexpected(),
&"string or map",
));
}
};
visitor.visit_enum(EnumDeserializer { variant, value })
} }
#[inline] #[inline]
@ -436,7 +467,7 @@ impl<'de> serde::Deserializer<'de> for Value {
V: Visitor<'de>, V: Visitor<'de>,
{ {
match self { match self {
Value::Object(v) => visit_object(v, visitor), Value::Object(v) => v.deserialize_any(visitor),
_ => Err(self.invalid_type(&visitor)), _ => Err(self.invalid_type(&visitor)),
} }
} }
@ -452,7 +483,7 @@ impl<'de> serde::Deserializer<'de> for Value {
{ {
match self { match self {
Value::Array(v) => visit_array(v, visitor), Value::Array(v) => visit_array(v, visitor),
Value::Object(v) => visit_object(v, visitor), Value::Object(v) => v.deserialize_any(visitor),
_ => Err(self.invalid_type(&visitor)), _ => Err(self.invalid_type(&visitor)),
} }
} }
@ -566,8 +597,10 @@ impl<'de> VariantAccess<'de> for VariantDeserializer {
where where
V: Visitor<'de>, V: Visitor<'de>,
{ {
use serde::de::Deserializer;
match self.value { match self.value {
Some(Value::Object(v)) => visit_object(v, visitor), Some(Value::Object(v)) => v.deserialize_any(visitor),
Some(other) => Err(serde::de::Error::invalid_type( Some(other) => Err(serde::de::Error::invalid_type(
other.unexpected(), other.unexpected(),
&"struct variant", &"struct variant",
@ -708,21 +741,71 @@ where
} }
} }
fn visit_object_ref<'de, V>(object: &'de Map<String, Value>, visitor: V) -> Result<V::Value, Error> impl<'de> serde::Deserializer<'de> for &'de Map<String, Value> {
where type Error = Error;
V: Visitor<'de>,
{ fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
let len = object.len(); where
let mut deserializer = MapRefDeserializer::new(object); V: Visitor<'de>,
let map = tri!(visitor.visit_map(&mut deserializer)); {
let remaining = deserializer.iter.len(); let len = self.len();
if remaining == 0 { let mut deserializer = MapRefDeserializer::new(self);
Ok(map) let map = tri!(visitor.visit_map(&mut deserializer));
} else { let remaining = deserializer.iter.len();
Err(serde::de::Error::invalid_length( if remaining == 0 {
len, Ok(map)
&"fewer elements in map", } else {
)) Err(serde::de::Error::invalid_length(
len,
&"fewer elements in map",
))
}
}
fn deserialize_enum<V>(
self,
_name: &'static str,
_variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
let mut iter = self.into_iter();
let (variant, value) = match iter.next() {
Some(v) => v,
None => {
return Err(serde::de::Error::invalid_value(
Unexpected::Map,
&"map with a single key",
));
}
};
// enums are encoded in json as maps with a single key:value pair
if iter.next().is_some() {
return Err(serde::de::Error::invalid_value(
Unexpected::Map,
&"map with a single key",
));
}
visitor.visit_enum(EnumRefDeserializer {
variant,
value: Some(value),
})
}
fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
visitor.visit_unit()
}
forward_to_deserialize_any! {
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
bytes byte_buf option unit unit_struct newtype_struct seq tuple
tuple_struct map struct identifier
} }
} }
@ -739,7 +822,7 @@ impl<'de> serde::Deserializer<'de> for &'de Value {
Value::Number(n) => n.deserialize_any(visitor), Value::Number(n) => n.deserialize_any(visitor),
Value::String(v) => visitor.visit_borrowed_str(v), Value::String(v) => visitor.visit_borrowed_str(v),
Value::Array(v) => visit_array_ref(v, visitor), Value::Array(v) => visit_array_ref(v, visitor),
Value::Object(v) => visit_object_ref(v, visitor), Value::Object(v) => v.deserialize_any(visitor),
} }
} }
@ -768,44 +851,24 @@ impl<'de> serde::Deserializer<'de> for &'de Value {
fn deserialize_enum<V>( fn deserialize_enum<V>(
self, self,
_name: &str, name: &'static str,
_variants: &'static [&'static str], variants: &'static [&'static str],
visitor: V, visitor: V,
) -> Result<V::Value, Error> ) -> Result<V::Value, Error>
where where
V: Visitor<'de>, V: Visitor<'de>,
{ {
let (variant, value) = match self { match self {
Value::Object(value) => { Value::Object(value) => value.deserialize_enum(name, variants, visitor),
let mut iter = value.into_iter(); Value::String(variant) => visitor.visit_enum(EnumRefDeserializer {
let (variant, value) = match iter.next() { variant,
Some(v) => v, value: None,
None => { }),
return Err(serde::de::Error::invalid_value( other => Err(serde::de::Error::invalid_type(
Unexpected::Map, other.unexpected(),
&"map with a single key", &"string or map",
)); )),
} }
};
// enums are encoded in json as maps with a single key:value pair
if iter.next().is_some() {
return Err(serde::de::Error::invalid_value(
Unexpected::Map,
&"map with a single key",
));
}
(variant, Some(value))
}
Value::String(variant) => (variant, None),
other => {
return Err(serde::de::Error::invalid_type(
other.unexpected(),
&"string or map",
));
}
};
visitor.visit_enum(EnumRefDeserializer { variant, value })
} }
#[inline] #[inline]
@ -933,7 +996,7 @@ impl<'de> serde::Deserializer<'de> for &'de Value {
V: Visitor<'de>, V: Visitor<'de>,
{ {
match self { match self {
Value::Object(v) => visit_object_ref(v, visitor), Value::Object(v) => v.deserialize_any(visitor),
_ => Err(self.invalid_type(&visitor)), _ => Err(self.invalid_type(&visitor)),
} }
} }
@ -949,7 +1012,7 @@ impl<'de> serde::Deserializer<'de> for &'de Value {
{ {
match self { match self {
Value::Array(v) => visit_array_ref(v, visitor), Value::Array(v) => visit_array_ref(v, visitor),
Value::Object(v) => visit_object_ref(v, visitor), Value::Object(v) => v.deserialize_any(visitor),
_ => Err(self.invalid_type(&visitor)), _ => Err(self.invalid_type(&visitor)),
} }
} }
@ -1046,8 +1109,10 @@ impl<'de> VariantAccess<'de> for VariantRefDeserializer<'de> {
where where
V: Visitor<'de>, V: Visitor<'de>,
{ {
use serde::de::Deserializer;
match self.value { match self.value {
Some(Value::Object(v)) => visit_object_ref(v, visitor), Some(Value::Object(v)) => v.deserialize_any(visitor),
Some(other) => Err(serde::de::Error::invalid_type( Some(other) => Err(serde::de::Error::invalid_type(
other.unexpected(), other.unexpected(),
&"struct variant", &"struct variant",