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

Flattening an Enum doesn't "consume" the fields #2200

Open
npmccallum opened this issue Apr 9, 2022 · 1 comment
Open

Flattening an Enum doesn't "consume" the fields #2200

npmccallum opened this issue Apr 9, 2022 · 1 comment

Comments

@npmccallum
Copy link

Here is a minimal example:

use std::collections::BTreeMap;
use serde::{Serialize, Deserialize};
use serde_json::{Value, from_slice};

#[derive(Serialize, Deserialize)]
#[serde(tag = "fruit")]
enum Fruit {
    #[serde(rename = "grape")]
    Grape {
        seedless: bool,
    },
    
    #[serde(rename = "banana")]
    Banana {
        ripe: bool,
    },
}

#[derive(Serialize, Deserialize)]
struct Basket {
    #[serde(flatten)]
    fruit: Fruit,

    #[serde(flatten)]
    other: BTreeMap<String, Value>
}

fn main() {
    let basket: Basket = from_slice(b"{ \"fruit\": \"banana\", \"ripe\": true, \"bread\": true }").unwrap();
    println!("{:?}", basket.other);
}

Which prints:

{"bread": Bool(true), "fruit": String("banana"), "ripe": Bool(true)}

This behavior differs from flattening other types, such as structs. For example:

use std::collections::BTreeMap;
use serde::{Serialize, Deserialize};
use serde_json::{Value, from_slice};

#[derive(Serialize, Deserialize)]
struct Fruit {
    fruit: String,
    ripe: bool,
}

#[derive(Serialize, Deserialize)]
struct Basket {
    #[serde(flatten)]
    fruit: Fruit,

    #[serde(flatten)]
    other: BTreeMap<String, Value>
}

fn main() {
    let basket: Basket = from_slice(b"{ \"fruit\": \"banana\", \"ripe\": true, \"bread\": true }").unwrap();
    println!("{:?}", basket.other);
}

Which prints:

{"bread": Bool(true)}
@tgross35
Copy link

A pretty fatal issue with this is that round trip deserialization->serialization->deserialize does not work. Deserializing creates the key in both the enum and the map. This key appears twice in the serialization (at least using serde_json), then deserializing again fails with a duplicate key error.

xJonathanLEI added a commit to xJonathanLEI/starknet-jsonrpc-codegen that referenced this issue Apr 2, 2024
Types with nested flatten fields don't work with `deny_unknown_fields`
due to an upstream `serde` bug:

serde-rs/serde#2200
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants