serde-rs / serde

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

`tag` is not affected by `rename_all` #2776

Open wmmc88 opened 2 months ago

wmmc88 commented 2 months ago

rename_all is useful in situations where the format you're serializing from and the format you're serializing to may have different forms (i.e. rename_all(serialize = "SCREAMING_SNAKE_CASE", deserialize = "kebab-case"). It seems that when specifying tag for enums, the tag name is not affected by the rename_all attribute. This leads to inconsistencies in the serialized/deserialized data. There is also no way to specify a different tag value for Serialize and Deserialize.

Example Output from serde_json::to_string_pretty:

{
  "FIRST_FIELD": 1,
  "SECOND_FIELD": 2,
  "THIRD_FIELD": {
    "enum-tag": "A",
    "FIELD_ONE": 13,
    "FIELD_TWO": 25
  }
}
{
  "FIRST_FIELD": 1,
  "SECOND_FIELD": 2,
  "THIRD_FIELD": {
    "enum-tag": "B",
    "FIELD1": 34,
    "FIELD2": 23
  }
}

Example Code:

use serde_derive::{Serialize, Deserialize}; // 1.0.203
use serde_json; // 1.0.119

#[derive(Serialize, Deserialize, Debug)]
#[serde(
    deny_unknown_fields,
    rename_all(serialize = "SCREAMING_SNAKE_CASE", deserialize = "kebab-case")
)]
struct S {
    first_field: u32,
    second_field: u32,
    third_field: E,
}

#[derive(Serialize, Deserialize, Debug)]
#[serde(
    tag = "enum-tag",
    deny_unknown_fields,
    rename_all(serialize = "SCREAMING_SNAKE_CASE", deserialize = "kebab-case"),
    rename_all_fields(serialize = "SCREAMING_SNAKE_CASE", deserialize = "kebab-case")
)]
enum E {
    A { field_one: u32, field_two: u32 },
    B { field1: u32, field2: u32 },
}

fn main() {
    let x = S {
        first_field: 1,
        second_field: 2,
        third_field: E::A {
            field_one: 13,
            field_two: 25,
        },
    };
    println!("{}", serde_json::to_string_pretty(&x).unwrap());

    let x = S {
        third_field: E::B {
            field1: 34,
            field2: 23,
        },
        ..x
    };
    println!("{}", serde_json::to_string_pretty(&x).unwrap());
}

playground link: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=f5b7b498f6ae4abfbd85b905a6b28b34

wmmc88 commented 2 months ago

something like #2324 would also resolve this issue