json icon indicating copy to clipboard operation
json copied to clipboard

Deserializing (tagged) Tuple Variant with no elements inside untagged enum results in error

Open pheki opened this issue 5 years ago • 1 comments

Hi!

If you have an enum such as

#[serde(untagged)]
enum TestBackwardCompatible {
    Test(Test)
}
enum Test {
    Empty()
}

It will serialize to {"Empty":[]} but deserialization will fail with data did not match any variant of untagged enum TestBackwardCompatible.

Some example code (playground):

use serde_derive::{Serialize, Deserialize};

#[derive(Serialize, Deserialize, Debug)]
#[serde(untagged)]
enum TestBackwardCompatible {
    Test(Test),
}

#[derive(Serialize, Deserialize, Debug)]
enum Test {
    Empty(),
    SingleElement(u8),
    MultiElement(u8, u8),
    ZeroElementArray([u8; 0]), // This is an workaround with expected behaviour
}

fn main() {
    // Some examples of what does not fail
    let text = serde_json::to_string(&TestBackwardCompatible::Test(Test::SingleElement(10))).unwrap();
    println!("{}", text);
    let data: TestBackwardCompatible = serde_json::from_str(&text).unwrap();
    println!("{:?}\n", data);

    let text = serde_json::to_string(&TestBackwardCompatible::Test(Test::MultiElement(10, 20))).unwrap();
    println!("{}", text);
    let data: TestBackwardCompatible = serde_json::from_str(&text).unwrap();
    println!("{:?}\n", data);

    let text = serde_json::to_string(&TestBackwardCompatible::Test(Test::ZeroElementArray([]))).unwrap();
    println!("{}", text);
    let data: TestBackwardCompatible = serde_json::from_str(&text).unwrap();
    println!("{:?}\n", data);
    
    // The problem lies here
    let text = serde_json::to_string(&TestBackwardCompatible::Test(Test::Empty())).unwrap();
    println!("{}", text);
    // Deserializing the variant directly works fine
    let data: Test = serde_json::from_str(&text).unwrap();
    println!("deserializing directly works: {:?}", data);
    // Deserializing it inside the untagged enum fails
    let data: TestBackwardCompatible = serde_json::from_str(&text).unwrap(); // panics!
    println!("this won't ever find its way to stdout: {:?}", data);
}

pheki avatar May 09 '20 07:05 pheki

Possibly related to https://github.com/serde-rs/serde/issues/1183

pheki avatar Aug 25 '20 04:08 pheki