diff --git a/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java b/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java index 09fee0197c..2558a22261 100644 --- a/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java +++ b/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java @@ -1181,37 +1181,53 @@ private List divideOperationsByContentType(String path, PathItem.Http if (content.size() <= 1) { return Collections.emptyList(); } + var firstEntry = content.entrySet().iterator().next(); var mediaTypesToRemove = new ArrayList(); for (var entry : content.entrySet()) { - if (mediaTypesToRemove.contains(entry.getKey())) { + if (mediaTypesToRemove.contains(entry.getKey()) || entry.getKey().equals(firstEntry.getKey()) || entry.getValue().equals(firstEntry.getValue())) { continue; } - for (var entry2 : content.entrySet()) { - if (entry.getKey().equals(entry2.getKey()) || entry.getValue().equals(entry2.getValue())) { - continue; + var foundSameOpSignature = false; + for (var additionalOp : additionalOps) { + RequestBody additionalBody = additionalOp.getRequestBody(); + if (additionalBody == null || additionalBody.getContent() == null) { + return Collections.emptyList(); + } + for (var addContentEntry : additionalBody.getContent().entrySet()) { + if (addContentEntry.getValue().equals(entry.getValue())) { + foundSameOpSignature = true; + break; + } + } + if (foundSameOpSignature) { + additionalBody.getContent().put(entry.getKey(), entry.getValue()); + break; } - additionalOps.add(new Operation() - .deprecated(op.getDeprecated()) - .callbacks(op.getCallbacks()) - .description(op.getDescription()) - .extensions(op.getExtensions()) - .externalDocs(op.getExternalDocs()) - .operationId(getOrGenerateOperationId(op, path, httpMethod.name())) - .parameters(op.getParameters()) - .responses(op.getResponses()) - .security(op.getSecurity()) - .servers(op.getServers()) - .summary(op.getSummary()) - .tags(op.getTags()) - .requestBody(new RequestBody() - .description(body.getDescription()) - .extensions(body.getExtensions()) - .content(new Content() - .addMediaType(entry2.getKey(), entry2.getValue())) - ) - ); - mediaTypesToRemove.add(entry2.getKey()); } + mediaTypesToRemove.add(entry.getKey()); + if (foundSameOpSignature) { + continue; + } + additionalOps.add(new Operation() + .deprecated(op.getDeprecated()) + .callbacks(op.getCallbacks()) + .description(op.getDescription()) + .extensions(op.getExtensions()) + .externalDocs(op.getExternalDocs()) + .operationId(getOrGenerateOperationId(op, path, httpMethod.name())) + .parameters(op.getParameters()) + .responses(op.getResponses()) + .security(op.getSecurity()) + .servers(op.getServers()) + .summary(op.getSummary()) + .tags(op.getTags()) + .requestBody(new RequestBody() + .description(body.getDescription()) + .extensions(body.getExtensions()) + .content(new Content() + .addMediaType(entry.getKey(), entry.getValue())) + ) + ); } if (!mediaTypesToRemove.isEmpty()) { content.entrySet().removeIf(stringMediaTypeEntry -> mediaTypesToRemove.contains(stringMediaTypeEntry.getKey())); diff --git a/openapi-generator/src/test/java/io/micronaut/openapi/generator/JavaMicronautClientCodegenTest.java b/openapi-generator/src/test/java/io/micronaut/openapi/generator/JavaMicronautClientCodegenTest.java index 8df3303337..60e8da69a5 100644 --- a/openapi-generator/src/test/java/io/micronaut/openapi/generator/JavaMicronautClientCodegenTest.java +++ b/openapi-generator/src/test/java/io/micronaut/openapi/generator/JavaMicronautClientCodegenTest.java @@ -771,6 +771,7 @@ void testMultipleContentTypesEndpoints() { assertFileContains(path + "api/DefaultApi.java", """ @Post("/multiplecontentpath") + @Produces({"application/json", "application/xml"}) Mono> myOp( @Body @Nullable @Valid Coordinates coordinates ); @@ -782,6 +783,13 @@ Mono> myOp_1( @Nullable @Valid Coordinates coordinates, @Nullable byte[] file ); + """, + """ + @Post("/multiplecontentpath") + @Produces({"application/yaml", "text/json"}) + Mono> myOp_2( + @Body @Nullable @Valid MySchema mySchema + ); """); } diff --git a/openapi-generator/src/test/java/io/micronaut/openapi/generator/JavaMicronautServerCodegenTest.java b/openapi-generator/src/test/java/io/micronaut/openapi/generator/JavaMicronautServerCodegenTest.java index 4cab20e3b4..3055abce48 100644 --- a/openapi-generator/src/test/java/io/micronaut/openapi/generator/JavaMicronautServerCodegenTest.java +++ b/openapi-generator/src/test/java/io/micronaut/openapi/generator/JavaMicronautServerCodegenTest.java @@ -537,21 +537,14 @@ void testMultipleContentTypesEndpoints() { String path = outputPath + "src/main/java/org/openapitools/"; assertFileContains(path + "api/DefaultApi.java", """ - @Operation( - operationId = "myOp", - responses = @ApiResponse(responseCode = "201", description = "Successfully created") - ) @Post("/multiplecontentpath") + @Consumes({"application/json", "application/xml"}) @Secured(SecurityRule.IS_ANONYMOUS) Mono> myOp( @Body @Nullable(inherited = true) @Valid Coordinates coordinates ); """, """ - @Operation( - operationId = "myOp_0", - responses = @ApiResponse(responseCode = "201", description = "Successfully created") - ) @Post("/multiplecontentpath") @Consumes("multipart/form-data") @Secured(SecurityRule.IS_ANONYMOUS) @@ -559,6 +552,14 @@ Mono> myOp_1( @Nullable(inherited = true) @Valid Coordinates coordinates, @Nullable(inherited = true) CompletedFileUpload file ); + """, + """ + @Post("/multiplecontentpath") + @Consumes({"application/yaml", "text/json"}) + @Secured(SecurityRule.IS_ANONYMOUS) + Mono> myOp_2( + @Body @Nullable(inherited = true) @Valid MySchema mySchema + ); """); } } diff --git a/openapi-generator/src/test/java/io/micronaut/openapi/generator/KotlinMicronautClientCodegenTest.java b/openapi-generator/src/test/java/io/micronaut/openapi/generator/KotlinMicronautClientCodegenTest.java index a16c8a48db..347c6d1a7c 100644 --- a/openapi-generator/src/test/java/io/micronaut/openapi/generator/KotlinMicronautClientCodegenTest.java +++ b/openapi-generator/src/test/java/io/micronaut/openapi/generator/KotlinMicronautClientCodegenTest.java @@ -796,6 +796,7 @@ void testMultipleContentTypesEndpoints() { assertFileContains(path + "api/DefaultApi.kt", """ @Post("/multiplecontentpath") + @Produces("application/json", "application/xml") fun myOp( @Body @Nullable @Valid coordinates: Coordinates? ): Mono> @@ -807,6 +808,13 @@ fun myOp_1( @Nullable @Valid coordinates: Coordinates?, @Nullable file: ByteArray? ): Mono> + """, + """ + @Post("/multiplecontentpath") + @Produces("application/yaml", "text/json") + fun myOp_2( + @Body @Nullable @Valid mySchema: MySchema? + ): Mono> """); } diff --git a/openapi-generator/src/test/java/io/micronaut/openapi/generator/KotlinMicronautServerCodegenTest.java b/openapi-generator/src/test/java/io/micronaut/openapi/generator/KotlinMicronautServerCodegenTest.java index 16466af50f..7d297f5b7c 100644 --- a/openapi-generator/src/test/java/io/micronaut/openapi/generator/KotlinMicronautServerCodegenTest.java +++ b/openapi-generator/src/test/java/io/micronaut/openapi/generator/KotlinMicronautServerCodegenTest.java @@ -1,6 +1,5 @@ package io.micronaut.openapi.generator; -import io.micronaut.openapi.generator.assertions.TestUtils; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.servers.Server; @@ -622,25 +621,14 @@ void testMultipleContentTypesEndpoints() { String path = outputPath + "src/main/kotlin/org/openapitools/"; assertFileContains(path + "api/DefaultApi.kt", """ - @Operation( - operationId = "myOp", - responses = [ - ApiResponse(responseCode = "201", description = "Successfully created") - ] - ) @Post("/multiplecontentpath") + @Consumes("application/json", "application/xml") @Secured(SecurityRule.IS_ANONYMOUS) fun myOp( @Body @Nullable @Valid coordinates: Coordinates? ): Mono> """, """ - @Operation( - operationId = "myOp_0", - responses = [ - ApiResponse(responseCode = "201", description = "Successfully created") - ] - ) @Post("/multiplecontentpath") @Consumes("multipart/form-data") @Secured(SecurityRule.IS_ANONYMOUS) @@ -648,6 +636,14 @@ fun myOp_1( @Nullable @Valid coordinates: Coordinates?, @Nullable file: CompletedFileUpload? ): Mono> + """, + """ + @Post("/multiplecontentpath") + @Consumes("application/yaml", "text/json") + @Secured(SecurityRule.IS_ANONYMOUS) + fun myOp_2( + @Body @Nullable @Valid mySchema: MySchema? + ): Mono> """); } } diff --git a/openapi-generator/src/test/resources/3_0/multiple-content-types.yml b/openapi-generator/src/test/resources/3_0/multiple-content-types.yml index 495df001f0..f2cfcaf949 100644 --- a/openapi-generator/src/test/resources/3_0/multiple-content-types.yml +++ b/openapi-generator/src/test/resources/3_0/multiple-content-types.yml @@ -11,6 +11,9 @@ paths: application/json: schema: $ref: '#/components/schemas/coordinates' + application/xml: + schema: + $ref: '#/components/schemas/coordinates' multipart/form-data: schema: type: object @@ -20,6 +23,12 @@ paths: file: type: string format: binary + application/yaml: + schema: + $ref: '#/components/schemas/MySchema' + text/json: + schema: + $ref: '#/components/schemas/MySchema' responses: 201: description: Successfully created @@ -39,3 +48,10 @@ components: type: number long: type: number + MySchema: + type: object + required: + - lat + properties: + lat: + type: number