From 321ce8d009d5edde22bed33c6c729968737919e8 Mon Sep 17 00:00:00 2001 From: Mattias-Sehlstedt <60173714+Mattias-Sehlstedt@users.noreply.github.com> Date: Fri, 14 Aug 2026 12:09:17 +0200 Subject: [PATCH] feat(core): expose request body named examples to templates --- .../openapitools/codegen/DefaultCodegen.java | 43 +++++++++++++++++-- .../codegen/DefaultCodegenTest.java | 20 +++++++++ .../src/test/resources/3_0/examples.yaml | 24 +++++++++++ 3 files changed, 83 insertions(+), 4 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java index 6d6c631aec1e..f9cfefa8ad69 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java @@ -2456,6 +2456,18 @@ public void setParameterExamples(CodegenParameter codegenParameter, Parameter pa } } + /** + * Return the examples of the parameter. + * + * @param codegenParameter Codegen parameter + * @param mediaType Media type + */ + public void setParameterExamples(CodegenParameter codegenParameter, MediaType mediaType) { + if (mediaType.getExamples() != null && !mediaType.getExamples().isEmpty()) { + codegenParameter.examples = mediaType.getExamples(); + } + } + /** * Return the example value of the parameter. * @@ -7442,13 +7454,33 @@ public void writePropertyBack(String propertyKey, Object value) { } protected String getContentType(RequestBody requestBody) { - if (requestBody == null || requestBody.getContent() == null || requestBody.getContent().isEmpty()) { + if (!hasMediaType(requestBody)) { LOGGER.debug("Cannot determine the content type. Returning null."); return null; } return new ArrayList<>(requestBody.getContent().keySet()).get(0); } + /** + * + * @param requestBody The request body + * @return The first media type of the request body's content, if it exists. Otherwise, returns an empty Optional. + */ + private Optional getFirstContentMediaType(RequestBody requestBody) { + if (hasMediaType(requestBody)) { + return Optional.of(requestBody.getContent().values().iterator().next()); + } + return Optional.empty(); + } + + private static boolean hasMediaType(RequestBody requestBody) { + return requestBody != null && requestBody.getContent() != null && !requestBody.getContent().isEmpty(); + } + + private static boolean hasMediaType(ApiResponse apiResponse) { + return apiResponse != null && apiResponse.getContent() != null && !apiResponse.getContent().isEmpty(); + } + private void setOauth2Info(CodegenSecurity codegenSecurity, OAuthFlow flow) { codegenSecurity.authorizationUrl = flow.getAuthorizationUrl(); codegenSecurity.tokenUrl = flow.getTokenUrl(); @@ -7481,7 +7513,7 @@ private void setOpenIdConnectInfo(CodegenSecurity codegenSecurity, OAuthFlow flo private void addConsumesInfo(Operation operation, CodegenOperation codegenOperation) { RequestBody requestBody = ModelUtils.getReferencedRequestBody(this.openAPI, operation.getRequestBody()); - if (requestBody == null || requestBody.getContent() == null || requestBody.getContent().isEmpty()) { + if (!hasMediaType(requestBody)) { return; } @@ -7512,7 +7544,7 @@ private void addConsumesInfo(Operation operation, CodegenOperation codegenOperat public static Set getConsumesInfo(OpenAPI openAPI, Operation operation) { RequestBody requestBody = ModelUtils.getReferencedRequestBody(openAPI, operation.getRequestBody()); - if (requestBody == null || requestBody.getContent() == null || requestBody.getContent().isEmpty()) { + if (!hasMediaType(requestBody)) { return Collections.emptySet(); // return empty set } return requestBody.getContent().keySet(); @@ -7548,7 +7580,7 @@ public boolean hasBodyParameter(Operation operation) { private void addProducesInfo(ApiResponse inputResponse, CodegenOperation codegenOperation) { ApiResponse response = ModelUtils.getReferencedApiResponse(this.openAPI, inputResponse); - if (response == null || response.getContent() == null || response.getContent().isEmpty()) { + if (!hasMediaType(response)) { return; } @@ -8376,6 +8408,9 @@ public CodegenParameter fromRequestBody(RequestBody body, Set imports, S // should be overridden by lang codegen setParameterExampleValue(codegenParameter, body); + getFirstContentMediaType(body) + .ifPresent(mediaType -> setParameterExamples(codegenParameter, mediaType)); + // restore original schema with description, extensions etc if (original != null) { // evaluate common attributes such as description if defined in the top level diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java index 72624f257e5a..49ec2f687df1 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java @@ -1156,6 +1156,26 @@ public void testExample5MultipleResponses() { assertEquals("500", examples.get(3).get("statusCode")); } + @Test + public void testExample6MultipleRequestBodyExamples() { + final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/examples.yaml"); + final DefaultCodegen codegen = new DefaultCodegen(); + codegen.setOpenAPI(openAPI); + String path = "/example6/multiple_examples"; + + Operation operation = openAPI.getPaths().get(path).getPost(); + CodegenOperation codegenOperation = codegen.fromOperation(path, "POST", operation, null); + CodegenParameter bodyParam = codegenOperation.bodyParam; + + assertEquals("An example6 value 1", bodyParam.example); + + // verify all named examples are populated in the body parameter's examples + assertEquals(3, bodyParam.examples.size()); + assertEquals("An example6 value 1", bodyParam.examples.get("FirstExample").getValue()); + assertEquals("An example6 value 2", bodyParam.examples.get("SecondExample").getValue()); + assertEquals("An example6 value 3", bodyParam.examples.get("ThirdExample").getValue()); + } + @Test public void testDiscriminator() { final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml"); diff --git a/modules/openapi-generator/src/test/resources/3_0/examples.yaml b/modules/openapi-generator/src/test/resources/3_0/examples.yaml index e9dc245330f5..c7f9e4645457 100644 --- a/modules/openapi-generator/src/test/resources/3_0/examples.yaml +++ b/modules/openapi-generator/src/test/resources/3_0/examples.yaml @@ -139,6 +139,30 @@ paths: schema: type: string example: an internal server error response example + /example6/multiple_examples: + post: + operationId: example6PostMultipleExamples + requestBody: + content: + application/json: + schema: + type: object + properties: + name: + type: string + examples: + FirstExample: + summary: The first example value + value: 'An example6 value 1' + SecondExample: + summary: The second example value + value: 'An example6 value 2' + ThirdExample: + summary: The third example value + value: 'An example6 value 3' + responses: + '200': + description: successful operation components: schemas: User: