Skip to content

Commit 5747fb8

Browse files
committed
fix(normalizer): simplify oneOf/anyOf with a single inline const/enum sub-schema
Previously EnumUtils.simplifyComposedSchemaWithEnums bailed out whenever a oneOf/anyOf had fewer than 2 sub-schemas, regardless of whether the lone sub-schema was a named \ (which should be preserved) or an inline const/enum literal (e.g. oneOf: [{const: FIAttached}]). For the inline case, the schema fell through to simplifyOneOfAnyOfWithOnlyOneNonNullSubSchema, which collapses to the sub-schema but does not convert const to enum and drops the parent's type/default/extensions, producing a plain string field instead of a generated enum (e.g. in C# generichost/netcore templates). Only skip simplification now when the sole sub-schema is a \, preserving reusable named enum schemas while correctly simplifying single-value inline const/enum oneOf/anyOf schemas.
1 parent 4242641 commit 5747fb8

11 files changed

Lines changed: 98 additions & 5 deletions

File tree

modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/EnumUtils.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,11 +118,20 @@ public static Schema simplifyComposedSchemaWithEnums(Schema schema,
118118
return schema;
119119
}
120120

121-
if (subSchemas.size() < 2) {
122-
//do not process if there's less than 2 sub-schemas. It will be normalized later, and this prevents
123-
//named enum schemas from being converted to inline enum schemas
121+
if (subSchemas.isEmpty()) {
124122
return schema;
125123
}
124+
125+
if (subSchemas.size() == 1) {
126+
Object onlySubSchema = subSchemas.get(0);
127+
// A lone $ref to a named schema is left as-is (it will be normalized later); this
128+
// prevents named enum schemas from being converted to inline enum schemas. An inline
129+
// const/enum sub-schema (e.g. `oneOf: [{const: foo}]`), however, is processed below so
130+
// that single-value enums are simplified the same way as multi-value ones.
131+
if (!(onlySubSchema instanceof Schema) || ((Schema) onlySubSchema).get$ref() != null) {
132+
return schema;
133+
}
134+
}
126135
String schemaType = ModelUtils.getType(schema);
127136

128137
for (Object item : subSchemas) {

modules/openapi-generator/src/test/java/org/openapitools/codegen/OpenAPINormalizerTest.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1725,6 +1725,30 @@ public void testOpenAPINormalizerSingleConstEnum31Spec() {
17251725
assertEquals(Arrays.asList(originalConst), normalizedTypeSchema.getEnum());
17261726
}
17271727

1728+
@Test
1729+
public void testOpenAPINormalizerSingleOneOfConstEnum31Spec() {
1730+
// reproduces https://github.com/OpenAPITools/openapi-generator/issues/ where a `oneOf` wrapping
1731+
// a single `const` sub-schema (as opposed to 2+ consts) was not simplified into a proper enum,
1732+
// and lost the parent's `type`/`default`/`x-omitempty` in the process.
1733+
OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_1/enum-single-value.yaml");
1734+
1735+
Schema schema = openAPI.getComponents().getSchemas().get("SingleValueOneOfConst_3_1");
1736+
Schema originalTypeSchema = (Schema) schema.getProperties().get("type");
1737+
assertEquals(originalTypeSchema.getOneOf().size(), 1);
1738+
1739+
OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, Map.of());
1740+
openAPINormalizer.normalize();
1741+
1742+
Schema schema2 = openAPI.getComponents().getSchemas().get("SingleValueOneOfConst_3_1");
1743+
Schema normalizedTypeSchema = (Schema) schema2.getProperties().get("type");
1744+
assertTrue(ModelUtils.isEnumSchema(normalizedTypeSchema));
1745+
assertNull(normalizedTypeSchema.getOneOf());
1746+
assertEquals(normalizedTypeSchema.getEnum(), List.of("this-is-my-only-value"));
1747+
assertEquals(ModelUtils.getType(normalizedTypeSchema), "string");
1748+
assertEquals(normalizedTypeSchema.getDefault(), "this-is-my-only-value");
1749+
assertEquals(normalizedTypeSchema.getExtensions().get("x-omitempty"), true);
1750+
}
1751+
17281752
@Test
17291753
public void testOpenAPINormalizerProcessingAllOfSchema31Spec() {
17301754
// to test array schema processing in 3.1 spec

modules/openapi-generator/src/test/resources/3_1/enum-single-value.yaml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,15 @@ components:
1717
properties:
1818
type:
1919
enum:
20-
- this-is-my-only-value
20+
- this-is-my-only-value
21+
SingleValueOneOfConst_3_1:
22+
required:
23+
- type
24+
properties:
25+
type:
26+
type: string
27+
default: this-is-my-only-value
28+
x-omitempty: true
29+
oneOf:
30+
- const: this-is-my-only-value
31+
description: the only allowed value

samples/client/others/typescript/builds/enum-single-value/.openapi-generator/FILES

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

samples/client/others/typescript/builds/enum-single-value/models/ObjectSerializer.ts

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

samples/client/others/typescript/builds/enum-single-value/models/SingleValueOneOfConst31.ts

Lines changed: 41 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

samples/client/others/typescript/builds/enum-single-value/models/all.ts

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

samples/client/others/typescript/builds/enum-single-value/types/ObjectParamAPI.ts

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

samples/client/others/typescript/builds/enum-single-value/types/ObservableAPI.ts

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

samples/client/others/typescript/builds/enum-single-value/types/PromiseAPI.ts

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)