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

Issue:
Deserialization from Value fails to catch unknown fields in struct variant
This is an inconsistency between `from_str` and `from_value`. In general these are supposed to have the same behavior on identical input.

```rust
use serde::de::{
    Deserialize, Deserializer, EnumAccess, IgnoredAny, MapAccess, VariantAccess, Visitor,
};
use serde_json::json;
use std::fmt;

#[derive(Debug)]
enum Enum {
    Variant { x: u8 },
}

impl<'de> Deserialize<'de> for Enum {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct EnumVisitor;

        impl<'de> Visitor<'de> for EnumVisitor {
            type Value = Enum;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("enum Enum")
            }

            fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
            where
                A: EnumAccess<'de>,
            {
                let (IgnoredAny, variant) = data.variant()?;
                variant.struct_variant(&["x"], self)
            }

            fn visit_map<A>(self, mut data: A) -> Result<Self::Value, A::Error>
            where
                A: MapAccess<'de>,
            {
                let mut x = 0;
                if let Some((IgnoredAny, value)) = data.next_entry()? {
                    x = value;
                }
                Ok(Enum::Variant { x })
            }
        }

        deserializer.deserialize_enum("Enum", &["Variant"], EnumVisitor)
    }
}

fn main() {
    let s = r#" {"Variant":{"x":0,"y":0}} "#;
    assert!(serde_json::from_str::<Enum>(s).is_err());

    let j = json!({"Variant":{"x":0,"y":0}});
    println!("{:?}", serde_json::from_value::<Enum>(j).unwrap());
}
```


Discussion / hints:

Fix patch:
diff --git a/src/value/de.rs b/src/value/de.rs
index 5ff011961..24ca82696 100644
--- a/src/value/de.rs
+++ b/src/value/de.rs
@@ -538,7 +538,7 @@ impl<'de> VariantAccess<'de> for VariantDeserializer {
         V: Visitor<'de>,
     {
         match self.value {
-            Some(Value::Object(v)) => visitor.visit_map(MapDeserializer::new(v)),
+            Some(Value::Object(v)) => visit_object(v, visitor),
             Some(other) => Err(serde::de::Error::invalid_type(
                 other.unexpected(),
                 &"struct variant",
@@ -1021,7 +1021,7 @@ impl<'de> VariantAccess<'de> for VariantRefDeserializer<'de> {
         V: Visitor<'de>,
     {
         match self.value {
-            Some(&Value::Object(ref v)) => visitor.visit_map(MapRefDeserializer::new(v)),
+            Some(&Value::Object(ref v)) => visit_object_ref(v, visitor),
             Some(other) => Err(serde::de::Error::invalid_type(
                 other.unexpected(),
                 &"struct variant",


Test patch:
diff --git a/tests/regression/issue795.rs b/tests/regression/issue795.rs
new file mode 100644
index 000000000..43198a33d
--- /dev/null
+++ b/tests/regression/issue795.rs
@@ -0,0 +1,57 @@
+use serde::de::{
+    Deserialize, Deserializer, EnumAccess, IgnoredAny, MapAccess, VariantAccess, Visitor,
+};
+use serde_json::json;
+use std::fmt;
+
+#[derive(Debug)]
+enum Enum {
+    Variant { x: u8 },
+}
+
+impl<'de> Deserialize<'de> for Enum {
+    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+    where
+        D: Deserializer<'de>,
+    {
+        struct EnumVisitor;
+
+        impl<'de> Visitor<'de> for EnumVisitor {
+            type Value = Enum;
+
+            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+                formatter.write_str("enum Enum")
+            }
+
+            fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
+            where
+                A: EnumAccess<'de>,
+            {
+                let (IgnoredAny, variant) = data.variant()?;
+                variant.struct_variant(&["x"], self)
+            }
+
+            fn visit_map<A>(self, mut data: A) -> Result<Self::Value, A::Error>
+            where
+                A: MapAccess<'de>,
+            {
+                let mut x = 0;
+                if let Some((IgnoredAny, value)) = data.next_entry()? {
+                    x = value;
+                }
+                Ok(Enum::Variant { x })
+            }
+        }
+
+        deserializer.deserialize_enum("Enum", &["Variant"], EnumVisitor)
+    }
+}
+
+#[test]
+fn test() {
+    let s = r#" {"Variant":{"x":0,"y":0}} "#;
+    assert!(serde_json::from_str::<Enum>(s).is_err());
+
+    let j = json!({"Variant":{"x":0,"y":0}});
+    assert!(serde_json::from_value::<Enum>(j).is_err());
+}