diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java index 68750b1bdefc..e9719363e7a6 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java @@ -1600,6 +1600,7 @@ protected Schema processSimplifyOneOfEnum(Schema schema) { */ protected Schema simplifyComposedSchemaWithEnums(Schema schema, List subSchemas, String composedType) { Map enumValues = new LinkedHashMap<>(); + Map deprecatedValues = new LinkedHashMap<>(); if(schema.getTypes() != null && schema.getTypes().size() > 1) { // we cannot handle enums with multiple types @@ -1620,10 +1621,15 @@ protected Schema simplifyComposedSchemaWithEnums(Schema schema, List sub Schema subSchema = ModelUtils.getReferencedSchema(openAPI, (Schema) item); - // Check if this sub-schema has an enum (with one or more values) - if (subSchema.getEnum() == null || subSchema.getEnum().isEmpty()) { + // Check if this sub-schema has an enum or const value (OAS 3.1 uses const for single-value enums) + boolean definesEnum = ModelUtils.hasEnum(subSchema); + if (!definesEnum && subSchema.getConst() == null) { return schema; } + // If const is present but enum is not, treat const as a single enum value + List subSchemaEnumValues = definesEnum + ? subSchema.getEnum() + : Arrays.asList(subSchema.getConst()); // Ensure all sub-schemas have the same type (if type is specified) if(subSchema.getTypes() != null && subSchema.getTypes().size() > 1) { @@ -1638,8 +1644,9 @@ protected Schema simplifyComposedSchemaWithEnums(Schema schema, List sub return schema; } } + boolean subSchemaDeprecated = Boolean.TRUE.equals(subSchema.getDeprecated()); // Add all enum values from this sub-schema to our collection - if(subSchema.getEnum().size() == 1) { + if(subSchemaEnumValues.size() == 1) { String description = subSchema.getTitle() == null ? "" : subSchema.getTitle(); if(subSchema.getDescription() != null) { if(!description.isEmpty()) { @@ -1647,16 +1654,18 @@ protected Schema simplifyComposedSchemaWithEnums(Schema schema, List sub } description += subSchema.getDescription(); } - enumValues.put(subSchema.getEnum().get(0), description); + enumValues.put(subSchemaEnumValues.get(0), description); + deprecatedValues.put(subSchemaEnumValues.get(0), subSchemaDeprecated); } else { - for(Object e: subSchema.getEnum()) { + for(Object e: subSchemaEnumValues) { enumValues.put(e, ""); + deprecatedValues.put(e, subSchemaDeprecated); } } } - return createSimplifiedEnumSchema(schema, enumValues, schemaType, composedType); + return createSimplifiedEnumSchema(schema, enumValues, deprecatedValues, schemaType, composedType); } @@ -1665,11 +1674,12 @@ protected Schema simplifyComposedSchemaWithEnums(Schema schema, List sub * * @param originalSchema Original schema to modify * @param enumValues Collected enum values + * @param deprecatedValues Per-value deprecated flags (aligned with enumValues key order) * @param schemaType Consistent type across sub-schemas * @param composedType Type of composed schema being simplified * @return Simplified enum schema */ - protected Schema createSimplifiedEnumSchema(Schema originalSchema, Map enumValues, String schemaType, String composedType) { + protected Schema createSimplifiedEnumSchema(Schema originalSchema, Map enumValues, Map deprecatedValues, String schemaType, String composedType) { // Clear the composed schema type if ("oneOf".equals(composedType)) { originalSchema.setOneOf(null); @@ -1687,6 +1697,10 @@ protected Schema createSimplifiedEnumSchema(Schema originalSchema, Map(enumValues.values())); } + if (deprecatedValues != null && deprecatedValues.values().stream().anyMatch(Boolean.TRUE::equals)) { + // preserve per-value deprecated flags from OAS 3.1 oneOf/anyOf + const sub-schemas + originalSchema.addExtension("x-enum-deprecated", new ArrayList<>(deprecatedValues.values())); + } LOGGER.debug("Simplified {} with enum sub-schemas to single enum: {}", composedType, originalSchema); diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/OpenAPINormalizerTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/OpenAPINormalizerTest.java index 87e96066c0bc..f92927928f15 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/OpenAPINormalizerTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/OpenAPINormalizerTest.java @@ -1536,9 +1536,16 @@ public void testOpenAPINormalizerSimplifyOneOfAnyOf31Spec() { assertEquals(schema14.getType(), null); Schema schema16 = openAPI.getComponents().getSchemas().get("TypeIntegerWithOneOf"); - assertEquals(schema16.getOneOf().size(),3); - assertEquals(((Schema) schema16.getOneOf().get(0)).getConst(), 1); - assertEquals(((Schema) schema16.getOneOf().get(0)).getDeprecated(), true); + // 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); + // per-value deprecated flags from oneOf sub-schemas should be preserved as x-enum-deprecated + List enumDeprecated = (List) schema16.getExtensions().get("x-enum-deprecated"); + assertEquals(enumDeprecated.size(), 3); + assertEquals(enumDeprecated.get(0), Boolean.TRUE); + assertEquals(enumDeprecated.get(1), Boolean.FALSE); + assertEquals(enumDeprecated.get(2), Boolean.FALSE); Schema schema18 = openAPI.getComponents().getSchemas().get("OneOfNullAndRef3"); // original oneOf removed and simplified to just $ref (oneOf sub-schema) instead