Repository: serde-rs/json (language: rust)

Issue:
Implement `Deserializer` for `Map<String, Value>` and `&Map<String, Value>`
Sometimes I want to work with a `Value` that I know to be a json object. `Map<String, Value>` is the correct type to use for this but it is not possible to deserialize from a `Map<String, Value>` to a more concrete without going through `Value`. It would be nice if `Map<String, Value>` implemented `Deserializer`  so this all just works.

My actual use case is that I have a `&Map<String, Value>` that I would like to deserialize to a concrete struct, which is harder to come up with a workaround for. With an owned value I could just do `T::deserialize(Value::Object(map))` but that doesn't work for a reference.


Discussion / hints:

Fix patch:
diff --git a/src/map.rs b/src/map.rs
index 520cd6cf5..c4a2434d4 100644
--- a/src/map.rs
+++ b/src/map.rs
@@ -535,6 +535,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.
diff --git a/src/value/de.rs b/src/value/de.rs
index 936725635..848d8ce1d 100644
--- a/src/value/de.rs
+++ b/src/value/de.rs
@@ -187,21 +187,72 @@ where
     }
 }
 
-fn visit_object<'de, V>(object: Map<String, Value>, visitor: V) -> Result<V::Value, Error>
-where
-    V: Visitor<'de>,
-{
-    let len = object.len();
-    let mut deserializer = MapDeserializer::new(object);
-    let map = tri!(visitor.visit_map(&mut deserializer));
-    let remaining = deserializer.iter.len();
-    if remaining == 0 {
-        Ok(map)
-    } else {
-        Err(serde::de::Error::invalid_length(
-            len,
-            &"fewer elements in map",
-        ))
+impl<'de> serde::Deserializer<'de> for Map<String, Value> {
+    type Error = Error;
+
+    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+    where
+        V: Visitor<'de>,
+    {
+        let len = self.len();
+        let mut deserializer = MapDeserializer::new(self);
+        let map = tri!(visitor.visit_map(&mut deserializer));
+        let remaining = deserializer.iter.len();
+        if remaining == 0 {
+            Ok(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
     }
 }
 
@@ -222,7 +273,7 @@ impl<'de> serde::Deserializer<'de> for Value {
             #[cfg(not(any(feature = "std", feature = "alloc")))]
             Value::String(_) => unreachable!(),
             Value::Array(v) => visit_array(v, visitor),
-            Value::Object(v) => visit_object(v, visitor),
+            Value::Object(v) => v.deserialize_any(visitor),
         }
     }
 
@@ -253,44 +304,24 @@ impl<'de> serde::Deserializer<'de> for Value {
     #[inline]
     fn deserialize_enum<V>(
         self,
-        _name: &str,
-        _variants: &'static [&'static str],
+        name: &'static str,
+        variants: &'static [&'static str],
         visitor: V,
     ) -> Result<V::Value, Error>
     where
         V: Visitor<'de>,
     {
-        let (variant, value) = match self {
-            Value::Object(value) => {
-                let mut iter = value.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",
-                    ));
-                }
-                (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 })
+        match self {
+            Value::Object(value) => value.deserialize_enum(name, variants, visitor),
+            Value::String(variant) => visitor.visit_enum(EnumDeserializer {
+                variant,
+                value: None,
+            }),
+            other => Err(serde::de::Error::invalid_type(
+                other.unexpected(),
+                &"string or map",
+            )),
+        }
     }
 
     #[inline]
@@ -420,7 +451,7 @@ impl<'de> serde::Deserializer<'de> for Value {
         V: Visitor<'de>,
     {
         match self {
-            Value::Object(v) => visit_object(v, visitor),
+            Value::Object(v) => v.deserialize_any(visitor),
             _ => Err(self.invalid_type(&visitor)),
         }
     }
@@ -436,7 +467,7 @@ impl<'de> serde::Deserializer<'de> for Value {
     {
         match self {
             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)),
         }
     }
@@ -550,8 +581,10 @@ impl<'de> VariantAccess<'de> for VariantDeserializer {
     where
         V: Visitor<'de>,
     {
+        use serde::de::Deserializer;
+
         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(
                 other.unexpected(),
                 &"struct variant",
@@ -692,21 +725,71 @@ where
     }
 }
 
-fn visit_object_ref<'de, V>(object: &'de Map<String, Value>, visitor: V) -> Result<V::Value, Error>
-where
-    V: Visitor<'de>,
-{
-    let len = object.len();
-    let mut deserializer = MapRefDeserializer::new(object);
-    let map = tri!(visitor.visit_map(&mut deserializer));
-    let remaining = deserializer.iter.len();
-    if remaining == 0 {
-        Ok(map)
-    } else {
-        Err(serde::de::Error::invalid_length(
-            len,
-            &"fewer elements in map",
-        ))
+impl<'de> serde::Deserializer<'de> for &'de Map<String, Value> {
+    type Error = Error;
+
+    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+    where
+        V: Visitor<'de>,
+    {
+        let len = self.len();
+        let mut deserializer = MapRefDeserializer::new(self);
+        let map = tri!(visitor.visit_map(&mut deserializer));
+        let remaining = deserializer.iter.len();
+        if remaining == 0 {
+            Ok(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
     }
 }
 
@@ -723,7 +806,7 @@ impl<'de> serde::Deserializer<'de> for &'de Value {
             Value::Number(n) => n.deserialize_any(visitor),
             Value::String(v) => visitor.visit_borrowed_str(v),
             Value::Array(v) => visit_array_ref(v, visitor),
-            Value::Object(v) => visit_object_ref(v, visitor),
+            Value::Object(v) => v.deserialize_any(visitor),
         }
     }
 
@@ -752,44 +835,24 @@ impl<'de> serde::Deserializer<'de> for &'de Value {
 
     fn deserialize_enum<V>(
         self,
-        _name: &str,
-        _variants: &'static [&'static str],
+        name: &'static str,
+        variants: &'static [&'static str],
         visitor: V,
     ) -> Result<V::Value, Error>
     where
         V: Visitor<'de>,
     {
-        let (variant, value) = match self {
-            Value::Object(value) => {
-                let mut iter = value.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",
-                    ));
-                }
-                (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 })
+        match self {
+            Value::Object(value) => value.deserialize_enum(name, variants, visitor),
+            Value::String(variant) => visitor.visit_enum(EnumRefDeserializer {
+                variant,
+                value: None,
+            }),
+            other => Err(serde::de::Error::invalid_type(
+                other.unexpected(),
+                &"string or map",
+            )),
+        }
     }
 
     #[inline]
@@ -917,7 +980,7 @@ impl<'de> serde::Deserializer<'de> for &'de Value {
         V: Visitor<'de>,
     {
         match self {
-            Value::Object(v) => visit_object_ref(v, visitor),
+            Value::Object(v) => v.deserialize_any(visitor),
             _ => Err(self.invalid_type(&visitor)),
         }
     }
@@ -933,7 +996,7 @@ impl<'de> serde::Deserializer<'de> for &'de Value {
     {
         match self {
             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)),
         }
     }
@@ -1030,8 +1093,10 @@ impl<'de> VariantAccess<'de> for VariantRefDeserializer<'de> {
     where
         V: Visitor<'de>,
     {
+        use serde::de::Deserializer;
+
         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(
                 other.unexpected(),
                 &"struct variant",


Test patch: