GREsau / okapi

OpenAPI (AKA Swagger) document generation for Rust projects
MIT License
578 stars 103 forks source link

Deriving `JsonSchema` for a struct that uses `serde_with::serde_as` results in incorrect types #114

Closed 0xOmarA closed 1 year ago

0xOmarA commented 1 year ago

I'm trying to derive JsonSchema on a struct that uses serde_as to represent numbers as strings. My struct looks like the following:

#[derive(JsonSchema)]
#[serde_as]
#[derive(Serialize, Deserialize)]
pub enum Value {
    U8 {
        #[serde_as(as = "DisplayFromStr")]
        value: u8,
    }
}

The #[serde_as(as = "DisplayFromStr")] line tells serde_as to serialize my number through ToString and deserialize it through FromStr. So it's a very useful thing to have especially when dealing with larger numbers such as u128.

When printing out the schema for this struct, I get the following:

{
   "oneOf":[
      {
         "type":"object",
         "required":[
            "type",
            "value"
         ],
         "properties":{
            "type":{
               "type":"string",
               "enum":[
                  "U8"
               ]
            },
            "value":{
               "type":"integer",
               "format":"uint8",
               "minimum":0.0
            }
         }
      }
   ]
}

In the above, it mentions that the type of value is "integer" which is not the type serialized or deserialized.

My question here is:

  1. Is there anything in this crate which can help me combat this issue.
  2. Should I use something else that is not the serde_with crate to get the ToString and FromStr behavior?
ralpha commented 1 year ago

This is an issue for schemars. But are a lot of the serde paramaters are implemented for schemars. As you can see here: https://github.com/GREsau/schemars/blob/master/schemars_derive/src/attr/schemars_to_serde.rs

The feature you request above might be less used. So you might have to create a PR yourself or use one of the implemented serde attributes.

I'll transfer the issue to schemars so you don't have to open a new issue there. Never mind, I can not transfer it. So you will have to open a new issue there. (you can just copy the content and refer to this issue to make sure people can find it)

0xOmarA commented 1 year ago

Regarding this, I have managed to solve my issue thus I will be closing this GH issue.

For future readers, I now add a manual schemars attribute to types that I serialize differently through serde_as stating that the type will be serialized as a different type. Here is a minimal example:

#[derive(Serialize, Deserialize, JsonSchema)]
#[serde(transparent)]
#[schemars(transparent)]
struct NumberAsString(
    #[schemars(with = "String")]
    #[serde_as("serde_with::DisplayFromStr")]
    u64
);