serde-rs / serde

Serialization framework for Rust
https://serde.rs/
Apache License 2.0
8.81k stars 747 forks source link

`skip_serializing_if` not works when an enum variant is a tuple and the enum has `#[serde(tag = "type", content = "value")]` #2721

Open nan01ab opened 3 months ago

nan01ab commented 3 months ago

Like this example, the enum has a serde derive #[serde(tag = "type", content = "value")], and skip_serializing_if of the second variant not works:

version: serde 1.0.197, serde_json 1.0.115

    #[derive(Debug, Serialize, Deserialize)]
    pub struct Foo(String, u64, #[serde(skip_serializing_if = "String::is_empty")] String);

    #[derive(Debug, Clone, Serialize, Deserialize)]
    #[serde(tag = "type", content = "value")]
    pub enum Bar {
        One { #[serde(skip_serializing_if = "String::is_empty")] value: String },

        // `skip_serializing_if` not works.
        Two(#[serde(skip_serializing_if = "String::is_empty")] String),

    }

    #[test]
    fn test_foo_bar() {
        let foo = Foo("hello".into(), 1, "".into());
        let json = serde_json::to_string(&foo)
            .expect("`to_string` should be ok");
        assert_eq!(&json, r#"["hello",1]"#); // skipped as expected

        let bar = Bar::One { value: "".into() };
        let json = serde_json::to_string(&bar)
            .expect("`to_string` should be ok");
        assert_eq!(&json, r#"{"type":"One","value":{}}"#); // skipped as expected

        let bar = Bar::Two("".into());
        let json = serde_json::to_string(&bar)
            .expect("`to_string` should be ok");
        assert_eq!(&json, r#"{"type":"Two"}"#); // assert failed, because json is `{"type":"Two","value":""}`
    }
Mingun commented 3 months ago

Could you check if #2520 solves this case too?