fix(normalizer): support OAS 3.1 annotated enums (oneOf + const) for consistent enum generation (C#)#23869
fix(normalizer): support OAS 3.1 annotated enums (oneOf + const) for consistent enum generation (C#)#23869nagabalaji-b wants to merge 6 commits into
Conversation
There was a problem hiding this comment.
3 issues found across 8 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| if (subSchema.getEnum() == null || subSchema.getEnum().isEmpty()) { | ||
| // Check if this sub-schema has an enum or const value (OpenAPI 3.1 uses const for single-value enums) | ||
| List<Object> subSchemaEnumValues = subSchema.getEnum(); | ||
| if ((subSchemaEnumValues == null || subSchemaEnumValues.isEmpty()) && subSchema.getConst() == null) { |
There was a problem hiding this comment.
Rather than doing (subSchemaEnumValues == null || subSchemaEnumValues.isEmpty()) twice, could we extract this to a variable boolean definesEnum = ModelUtils.hasEnum(subSchema) and then have
if (!definesEnum && subSchema.getConst() == null) {This could allow use to skip the comments almost entirely and instead allow the variable/method names be the explanation themselves.
| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| | ||
| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| | ||
| |sourceFolder|source folder for generated code| |OpenAPI/src| | ||
| |sourceFolder|source folder for generated code| |OpenAPI\src| |
There was a problem hiding this comment.
Are these path changes intentional?
|
Thanks for adjusting to the suggestions. 👍 I am not a maintainer of the project, so I cannot make a formal review with an approve. |
| // After normalization, oneOf with const values should be simplified to enum | ||
| assertEquals(schema16.getOneOf(), null); | ||
| assertEquals(schema16.getEnum().size(), 3); | ||
| assertEquals(schema16.getEnum().get(0), 1); |
There was a problem hiding this comment.
(I'm not repo maintainer but the PR is something I was thinking about myself: so thank you)
The test against deprecated (https://github.com/nagabalaji-b/openapi-generator/blob/3496c3b7cffbc0cdc728cc77bd64708b8ba6ae9a/modules/openapi-generator/src/test/resources/3_1/simplifyOneOfAnyOf_test.yaml#L133) is lost here (and the information from schema too)
Here, seems it is not possible with current enum support implementation ("simple" list of values and optional list of descriptions with x-enum-descriptions) to support enum as "schema" enabling to keep all "schemas" related information with no loss.
There was a problem hiding this comment.
@nagabalaji-b can you please take a look and add back the deprecated test?
There was a problem hiding this comment.
@wing328 Done. I added back the deprecated test coverage:
Code change: Modified simplifyComposedSchemaWithEnums() to collect and preserve per-value deprecated flags from OAS 3.1 oneOf/anyOf + const sub-schemas into x-enum-deprecated extension.
Test assertion: Added explicit checks in testOpenAPINormalizerSimplifyOneOfAnyOf31Spec() for TypeIntegerWithOneOf schema:
Verifies x-enum-deprecated list size = 3
Verifies flags match expected values: [true, false, false] (first enum value was deprecated in the original YAML)
Validation: Ran the test locally and confirmed BUILD SUCCESS.
The deprecated metadata from the annotated enum pattern (oneOf + const) is now preserved through normalization, so generators can access it via the x-enum-deprecated extension.
Summary
This PR addresses normalization for OpenAPI 3.1 annotated enums, where enum values are expressed using
oneOf+const. The main focus is on ensuring C# behavior aligns with traditional enum handling.Problem
OpenAPI 3.0 typically utilizes enum arrays. In contrast, OpenAPI 3.1 often adopts an annotated enum style with
oneOf+constand per-value descriptions. Prior to this fix, const-based composed schemas were not consistently simplified into enum-like schemas, potentially impacting strong enum generation in C#.Example (OAS 3.1)
Equivalent OAS 3.0 Shape
C# Before vs After
Before Fix (String Property)
The property is a plain string because
oneOf+constwas not normalized to enum semantics.After Fix (Strong Enum)
After normalization, the schema is recognized as an enum and generates a strongly-typed enum with the appropriate JSON converter and member attributes.
Actual Behavior Before
OAS 3.1
oneOf+constwas not consistently normalized to enum semantics. C# output could revert to non-enum-style modeling for this pattern.Expected Behavior
OAS 3.1
oneOf+constshould normalize in the same manner as OAS 3.0 enums. C# should consistently produce strongly typed enum output.Changes in This PR
constas a single enum value when an enum is absent in composed sub-schemas.oneOfandanyOfenum-like paths.C# Result After Fix (Illustrative)
Validation
The targeted normalizer test for OAS 3.1 simplifying
oneOf/anyOfpaths passed. Samples have been regenerated for Java configurations. Documentation for the generator has been exported.Compatibility
This is a bug fix only. No intended breaking behavior changes. The normalization improvement is generator-agnostic; C# is the primary verified use case.
PR Checklist
@muttleyxd @devhl-labs @lucasheim @shibayan (C# generators)
Summary by cubic
Normalize OpenAPI 3.1 annotated enums (
oneOf+const) as true enums. This ensures that C# code generation produces strong enums consistently, matching OAS 3.0 behavior.constas a single enum value when an enum is missing in sub-schemas.oneOf/anyOfenum-like schemas into a single enum in the parent, preserving types and per-value descriptions.Written for commit 51e0b0f. Summary will update with new commits. Review in cubic