diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/InlineModelResolver.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/InlineModelResolver.java index 94ad2cc38842..2887daa8ef29 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/InlineModelResolver.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/InlineModelResolver.java @@ -81,6 +81,8 @@ public class InlineModelResolver { // a set to keep track of names generated for inline schemas private Set uniqueNames = new HashSet<>(); + // names that were added through inlineSchemaNameMapping + private Set mappedSchemaNames = new HashSet<>(); // MixIn that suppresses volatile fields when any Schema instance is serialised for structural // comparison. Registered on Schema.class so it applies recursively to all nested Schema @@ -1182,13 +1184,17 @@ private void copyVendorExtensions(Schema source, Schema target) { private String addSchemas(String name, Schema schema) { //check inlineSchemaNameMapping if (inlineSchemaNameMapping.containsKey(name)) { + // use the name chosen by the user as is, even if several inline schemas map to it name = inlineSchemaNameMapping.get(name); - } - - // Recursive flattening can add a nested schema after its parent's name - // was chosen. Re-check here so the parent cannot overwrite that child. - if (openAPI.getComponents().getSchemas().containsKey(name) + if (openAPI.getComponents().getSchemas().containsKey(name) + && !uniqueNames.contains(name) && !mappedSchemaNames.contains(name)) { + LOGGER.warn("inlineSchemaNameMapping maps an inline schema to `{}`, which is already defined in the spec. The existing `{}` schema is replaced by the inline schema.", name, name); + } + mappedSchemaNames.add(name); + } else if (openAPI.getComponents().getSchemas().containsKey(name) || uniqueNames.contains(name)) { + // Recursive flattening can add a nested schema after its parent's name + // was chosen. Re-check here so the parent cannot overwrite that child. name = uniqueName(name); } diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/InlineModelResolverTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/InlineModelResolverTest.java index b6b81d765a03..bd696d01e721 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/InlineModelResolverTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/InlineModelResolverTest.java @@ -1258,6 +1258,25 @@ public void testInlineSchemaNameMapping() { assertTrue(nothingNew.getProperties().get("arbitrary_request_body_array_property") instanceof ObjectSchema); } + @Test + public void testInlineSchemaNameMappingManyToOne() { + OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/inline_schema_name_mapping_many_to_one.yaml"); + InlineModelResolver resolver = new InlineModelResolver(); + Map inlineSchemaNames = new HashMap<>(); + inlineSchemaNames.put("Preview_balance", "Money"); + inlineSchemaNames.put("Preview_interest", "Money"); + resolver.setInlineSchemaNameMapping(inlineSchemaNames); + resolver.flatten(openAPI); + + Map schemas = openAPI.getComponents().getSchemas(); + assertTrue(schemas.containsKey("Money")); + assertFalse(schemas.containsKey("Money_1")); + + Schema preview = schemas.get("Preview"); + assertEquals("#/components/schemas/Money", ((Schema) preview.getProperties().get("balance")).get$ref()); + assertEquals("#/components/schemas/Money", ((Schema) preview.getProperties().get("interest")).get$ref()); + } + @Test public void testInlineSchemaOptions() { OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/inline_model_resolver.yaml"); diff --git a/modules/openapi-generator/src/test/resources/3_0/inline_schema_name_mapping_many_to_one.yaml b/modules/openapi-generator/src/test/resources/3_0/inline_schema_name_mapping_many_to_one.yaml new file mode 100644 index 000000000000..4b9dbb2586e3 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/inline_schema_name_mapping_many_to_one.yaml @@ -0,0 +1,35 @@ +openapi: 3.0.3 +info: + title: inlineSchemaNameMappings many-to-one + version: "1" +paths: + /preview: + get: + responses: + "200": + description: ok + content: + application/json: + schema: + $ref: "#/components/schemas/Preview" +components: + schemas: + Preview: + type: object + properties: + balance: + type: object + description: The balance at the end of the range. + properties: + amount: + type: string + currency: + type: string + interest: + type: object + description: The interest accrued over the range. + properties: + amount: + type: string + currency: + type: string