GREsau / schemars

Generate JSON Schema documents from Rust code
https://graham.cool/schemars/
MIT License
791 stars 220 forks source link

enums: serde rename_all_fields not respected #273

Closed mguentner closed 2 weeks ago

mguentner commented 6 months ago

Description

When using serde's rename_all_fields on an enum together with schemars, the fields are not properly renamed in the schema. Only explicitly renaming each and every field renames them.

How to reproduce

use schemars::{schema_for, JsonSchema};
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, JsonSchema)]
#[derive(Debug, Clone, PartialEq)]
#[serde(tag = "Variant")]
#[serde(rename_all = "lowercase")]
#[serde(rename_all_fields = "PascalCase")]
pub enum Example {
    First {
        nested_attribute: String,
    },
    Second {
        #[serde(rename = "AnotherAttribute")]
        another_attribute: String,
    },
}

fn main() {
    let schema = schema_for!(Example);
    println!("{}", serde_json::to_string_pretty(&schema).unwrap());
    let example1 = Example::First { nested_attribute: "foo".to_owned()};
    println!("{}", serde_json::to_string_pretty(&example1).unwrap());
    let example2 = Example::Second { another_attribute: "foo".to_owned()};
    println!("{}", serde_json::to_string_pretty(&example2).unwrap());
}

Output:

❗ comments are mine

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Example",
  "oneOf": [
    {
      "type": "object",
      "required": [
        "Variant",
❗       "nested_attribute"  👈 snake_case, in spite of `rename_all_fields = "PascalCase"`
      ],
      "properties": {
        "Variant": {
          "type": "string",
          "enum": [
            "first"
          ]
        },
        "nested_attribute": {
          "type": "string"
        }
      }
    },
    {
      "type": "object",
      "required": [
❗       "AnotherAttribute", 👈 PascalCase!
        "Variant"
      ],
      "properties": {
        "AnotherAttribute": {
          "type": "string"
        },
        "Variant": {
          "type": "string",
          "enum": [
            "second"
          ]
        }
      }
    }
  ]
}
❗👇 json serialization output is the same in terms of capitalization 
{
  "Variant": "first",
  "NestedAttribute": "foo"
}
{
  "Variant": "second",
  "AnotherAttribute": "foo"
}