Repository: juhaku/utoipa (Rust)

Issue:
Externally tagged enum variants are not marked as required
The following Rust definition is translated to an OpenAPI schema where the variant tags (`One` and `Two`) are not marked as required, thus making them optional:

```rs
#[derive(Serialize, ToSchema)]
enum Foo {
    One { n: i32 },
    Two { bar: Bar },
}

#[derive(Serialize, ToSchema)]
struct Bar {
    name: String,
    age: u32,
}
```

The resulting OpenAPI schemas are:

```json
{
      "Bar": {
        "properties": {
          "age": {
            "format": "int32",
            "type": "integer"
          },
          "name": {
            "type": "string"
          }
        },
        "required": [
          "name",
          "age"
        ],
        "type": "object"
      },
      "Foo": {
        "oneOf": [
          {
            "properties": {
              "One": {
                "properties": {
                  "n": {
                    "format": "int32",
                    "type": "integer"
                  }
                },
                "required": [
                  "n"
                ],
                "type": "object"
              }
            },
            "type": "object"
          },
          {
            "properties": {
              "Two": {
                "properties": {
                  "bar": {
                    "$ref": "#/components/schemas/Bar"
                  }
                },
                "required": [
                  "bar"
                ],
                "type": "object"
              }
            },
            "type": "object"
          }
        ]
      }
    }
```

Since the tags are optional, the generator `typescript-axios` will generate the following TypeScript bindings:

```ts
interface Bar {
    'age': number;
    'name': string;
}

type Foo = FooOneOf | FooOneOf1;

interface FooOneOf {
    'One'?: FooOneOfOne;
}

interface FooOneOf1 {
    'Two'?: FooOneOf1Two;
}

interface FooOneOf1Two {
    'bar': Bar;
}

interface FooOneOfOne {
    'n': number;
}
```

With this definition, an empty object is a valid instance of the type `Foo`:

```ts
const foo: Foo = {};
```

This object is then unable to be deserialized by `serde`.


Discussion:
@philipahlberg Right, I can make them required though. 
Awesome, thanks!



Patch:
diff --git a/utoipa-gen/src/component/schema/enum_variant.rs b/utoipa-gen/src/component/schema/enum_variant.rs
index b87f2492..08b5eec5 100644
--- a/utoipa-gen/src/component/schema/enum_variant.rs
+++ b/utoipa-gen/src/component/schema/enum_variant.rs
@@ -74,6 +74,7 @@ where
             utoipa::openapi::schema::ObjectBuilder::new()
                 #title
                 .property(#name, #variant)
+                .required(#name)
         }
     }
 }


Test patch:
diff --git a/utoipa-gen/tests/schema_derive_test.rs b/utoipa-gen/tests/schema_derive_test.rs
index 888baf9e..0342037b 100644
--- a/utoipa-gen/tests/schema_derive_test.rs
+++ b/utoipa-gen/tests/schema_derive_test.rs
@@ -726,6 +726,7 @@ fn derive_complex_unnamed_field_reference_with_comment() {
                             "$ref": "#/components/schemas/CommentedReference",
                         },
                     },
+                    "required": ["UnnamedFieldWithCommentReference"],
                 },
             ],
         })
@@ -808,6 +809,7 @@ fn derive_complex_enum_with_schema_properties() {
                             "type": "object"
                         }
                     },
+                    "required": ["Variant"],
                     "type": "object"
                 },
                 {
@@ -822,6 +824,7 @@ fn derive_complex_enum_with_schema_properties() {
                             "type": "object"
                         }
                     },
+                    "required": ["Variant2"],
                     "type": "object"
                 }
             ]
@@ -1006,6 +1009,7 @@ fn derive_complex_enum() {
                             ],
                         },
                     },
+                    "required": ["NamedFields"],
                 },
                 {
                     "type": "object",
@@ -1014,6 +1018,7 @@ fn derive_complex_enum() {
                             "$ref": "#/components/schemas/Foo",
                         },
                     },
+                    "required": ["UnnamedFields"],
                 },
             ],
         })
@@ -1066,6 +1071,7 @@ fn derive_complex_enum_title() {
                             ],
                         },
                     },
+                    "required": ["NamedFields"],
                 },
                 {
                     "type": "object",
@@ -1075,6 +1081,7 @@ fn derive_complex_enum_title() {
                             "$ref": "#/components/schemas/Foo",
                         },
                     },
+                    "required": ["UnnamedFields"]
                 },
             ],
         })
@@ -1130,6 +1137,7 @@ fn derive_complex_enum_serde_rename_all() {
                             ],
                         },
                     },
+                    "required": ["named_fields"]
                 },
                 {
                     "type": "object",
@@ -1138,6 +1146,7 @@ fn derive_complex_enum_serde_rename_all() {
                             "$ref": "#/components/schemas/Foo",
                         },
                     },
+                    "required": ["unnamed_fields"]
                 },
             ],
         })
@@ -1197,6 +1206,7 @@ fn derive_complex_enum_serde_rename_variant() {
                             ],
                         },
                     },
+                    "required": ["renamed_named_fields"]
                 },
                 {
                     "type": "object",
@@ -1205,6 +1215,7 @@ fn derive_complex_enum_serde_rename_variant() {
                             "$ref": "#/components/schemas/Foo",
                         },
                     },
+                    "required": ["renamed_unnamed_fields"]
                 },
             ],
         })
@@ -1280,6 +1291,7 @@ fn derive_complex_enum_custom_rename() {
                             "type": "string"
                         }
                     },
+                    "required": ["NEWPOST"],
                     "type": "object",
                 },
                 {
@@ -1306,6 +1318,7 @@ fn derive_complex_enum_custom_rename() {
                             ]
                         }
                     },
+                    "required": ["update_post"],
                     "type": "object",
                 },
                 {
@@ -1323,6 +1336,7 @@ fn derive_complex_enum_custom_rename() {
                             ]
                         }
                     },
+                    "required": ["RANDOMVALUE"],
                     "type": "object",
                 }
             ]
@@ -1358,6 +1372,7 @@ fn derive_complex_enum_use_serde_rename_over_custom_rename() {
                         },
                     },
                     "type": "object",
+                    "required": ["string_value"]
                 },
                 {
                     "properties": {
@@ -1373,6 +1388,7 @@ fn derive_complex_enum_use_serde_rename_over_custom_rename() {
                         }
                     },
                     "type": "object",
+                    "required": ["number"]
                 }
             ]
         })
@@ -1450,6 +1466,7 @@ fn derive_complex_enum_with_title() {
                     },
                     "title": "admin",
                     "type": "object",
+                    "required": ["Admin"]
                 },
                 {
                     "properties": {
@@ -1464,6 +1481,7 @@ fn derive_complex_enum_with_title() {
                             "type": "object",
                         }
                     },
+                    "required": ["Moderator"],
                     "title": "moderator",
                     "type": "object",
                 },
@@ -2437,6 +2455,7 @@ fn derive_component_with_complex_enum_lifetimes() {
                             "type": "object"
                         },
                     },
+                    "required": ["A"],
                     "type": "object"
                 },
                 {
@@ -2855,6 +2874,7 @@ fn derive_enum_with_self_reference() {
                         }
                     },
                     "type": "object",
+                    "required": ["Item"],
                 },
                 {
                     "properties": {
@@ -2868,6 +2888,7 @@ fn derive_enum_with_self_reference() {
                             "type": "object",
                         }
                     },
+                    "required": ["Item2"],
                     "type": "object",
                 }
             ]