Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deserialization from Value fails to catch unknown fields in struct variant #795

Closed
dtolnay opened this issue Aug 28, 2021 · 0 comments · Fixed by #796
Closed

Deserialization from Value fails to catch unknown fields in struct variant #795

dtolnay opened this issue Aug 28, 2021 · 0 comments · Fixed by #796
Labels

Comments

@dtolnay
Copy link
Member

dtolnay commented Aug 28, 2021

This is an inconsistency between from_str and from_value. In general these are supposed to have the same behavior on identical input.

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());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

Successfully merging a pull request may close this issue.

1 participant