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

Adjacently tagged enum not deserialisable; ExpectedMap #87

Closed
happylinks opened this issue Nov 12, 2023 · 6 comments · Fixed by #89
Closed

Adjacently tagged enum not deserialisable; ExpectedMap #87

happylinks opened this issue Nov 12, 2023 · 6 comments · Fixed by #89

Comments

@happylinks
Copy link

happylinks commented Nov 12, 2023

I'm trying to deserialize my database which has a Map with a List as an enum, like background: ["Video", {url: "", duration:0}]
This should be supported by serde, but I'm now having a feeling it's not supported by serde_dynamo for some reason?

I found this issue where it's possible: serde-rs/serde#2479

#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
pub struct VideoBackgroundPayload {
    pub url: String,
    pub duration: f32,
}

#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[serde(tag = "0", content = "1")]
pub enum Background {
    Test(String),
    Video(VideoBackgroundPayload),
}

#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct User {
    id: String,
    background: Background,
}

// And deserialize them as strongly-typed data structures
let mut item = HashMap::new();

item.insert(
    "id".to_string(),
    AttributeValue::S("clnofe2cg0000ayeq6ryddrzw".to_string()),
);

let mut background_map = HashMap::new();
background_map.insert(
    "duration".to_string(),
    AttributeValue::N("7960".to_string()),
);
background_map.insert(
    "url".to_string(),
    AttributeValue::S("https://google.nl".to_string()),
);

let background = AttributeValue::M(background_map);
item.insert(
    "background".to_string(),
    AttributeValue::L(vec![
        AttributeValue::S("Video".to_string()),
        background,
    ]),
);

let user: Result<User, serde_dynamo::Error> = from_item(item.clone());
match user {
    Ok(user) => println!("user: {:#?}", user),
    Err(e) => println!("error: {:#?}", e),
}

Outputs:
error: Error(
    ExpectedMap,
)

deserialize_struct always calls deserialize_map and errors if it doesn't see a map as the value:

self.deserialize_map(visitor)

Let me know if I'm doing something wrong :)

@bryanburgers
Copy link
Contributor

Does the same approach work when you use the equivalent in serde_json?

@happylinks
Copy link
Author

I will properly test and confirm tomorrow when I'm at my desk again, but just quickly checking on my phone I see that it handles deserialize_struct in a way that also handles arrays: https://github.com/serde-rs/json/blob/4bc1eaa03a6160593575bc9bc60c94dba4cab1e3/src/de.rs#L1808

@happylinks
Copy link
Author

Can confirm that this works:

let user = r#"
    {
        "id": "clnofe2cg0000ayeq6ryddrzw",
        "background": ["Video", {"duration": 7960, "url": "https://google.nl"}]
    }"#;

// Parse the string of data into serde_json::Value.
let user: Result<User, serde_json::Error> = serde_json::from_str(user);
match user {
    Ok(user) => println!("user: {:#?}", user),
    Err(e) => println!("error: {:#?}", e),
}
user: User {
    id: "clnofe2cg0000ayeq6ryddrzw",
    background: Video(
        VideoBackgroundPayload {
            url: "https://google.nl",
            duration: 7960.0,
        },
    ),
}

bryanburgers added a commit that referenced this issue Nov 13, 2023
serde and serde_json have support for deserializing structs and
adjacently-tagged enums from sequences. I had no idea!

    #[derive(serde::Deserialize)]
    struct Person {
      name: String,
      age: u8,
    }

    let input = r#"["Arthur Dent", 42]"#;

    let person: Person = serde_json::from_str(input).unwrap();
    assert_eq!(person.name, "Arthur Dent");
    assert_eq!(person.age, 42);

Fixes #87
@bryanburgers
Copy link
Contributor

I didn't even realize this was a thing!

@bryanburgers
Copy link
Contributor

Thanks for reporting this! Fixed in 4.2.10.

@happylinks
Copy link
Author

Ah thanks so much for the fast fix! Awesome 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants