serde-rs/serde

Untagged and externally tagged enum at the same time

WaffleLapkin opened this issue · 2 comments

I'm not sure it's even possible, but it would be nice to have "externally tagged" variants and "untagged" variants at the same time.

Example:

#[derive(Debug, Deserialize, Serialize)]
enum Test {
    #[serde(rename = "tagged")]
    Tagged(i32),

    #[serde(untagged)]
    Untagged { field1: i32, field2: i32 }
}

#[test]
fn test() {
    let json = serde_json::to_string(&Test::Tagged(0)).unwrap();
    assert_eq!(json, r#"{"tagged":0}"#);

    let json = serde_json::to_string(&Test::Untagged { field1: 0, field2: 6 }).unwrap();
    assert_eq!(json, r#"{"field1":0,"field2":6}"#);
}

For now I'm just using

#[serde(untagged)]
enum Test {
    Tagged { tagged: i32 },
    Untagged { field1: i32, field2: i32 }
}

But there are duplication (like Tagged and tagged) in half enum variants and it isn't user-friendly (and in real life enum is much bigger and writing (de)serialization by hand can be painful)

I think I would prefer not to build this into serde_derive — but there is room for someone to create a more fully featured derive macro that can accommodate such a representation.

Mingun commented

This actually was implemented in #2403