diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/service/RequestBodyService.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/service/RequestBodyService.java index 0f48e5f8e..07bc63b0f 100644 --- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/service/RequestBodyService.java +++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/service/RequestBodyService.java @@ -285,9 +285,11 @@ public void calculateRequestBodyInfo(Components components, MethodAttributes met * @param requestBodyInfo the request body info * @return the request body */ - private RequestBody buildRequestBody(io.swagger.v3.oas.annotations.parameters.RequestBody requestBodyDoc, Components components, - MethodAttributes methodAttributes, - ParameterInfo parameterInfo, RequestBodyInfo requestBodyInfo) { + private RequestBody buildRequestBody(io.swagger.v3.oas.annotations.parameters.RequestBody requestBodyDoc, + Components components, + MethodAttributes methodAttributes, + ParameterInfo parameterInfo, + RequestBodyInfo requestBodyInfo) { RequestBody requestBody = requestBodyInfo.getRequestBody(); if (requestBody == null) { requestBody = new RequestBody(); @@ -300,7 +302,9 @@ private RequestBody buildRequestBody(io.swagger.v3.oas.annotations.parameters.Re Schema schema = parameterBuilder.calculateSchema(components, parameterInfo, requestBodyInfo, methodAttributes.getJsonViewAnnotationForRequestBody()); Map parameterEncoding = getParameterEncoding(parameterInfo); - buildContent(requestBody, methodAttributes, schema, parameterEncoding); + // If a content type is explicitly stated with a @RequestBody annotation, yield to that content type + if (!methodAttributes.isWithResponseBodySchemaDoc()) + buildContent(requestBody, methodAttributes, schema, parameterEncoding); // Add requestBody javadoc if (StringUtils.isBlank(requestBody.getDescription()) && parameterBuilder.getJavadocProvider() != null diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app244/HelloController.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app244/HelloController.java new file mode 100644 index 000000000..1c956bfa4 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app244/HelloController.java @@ -0,0 +1,85 @@ +/* + * + * * + * * * + * * * * + * * * * * + * * * * * * Copyright 2019-2025 the original author or authors. + * * * * * * + * * * * * * Licensed under the Apache License, Version 2.0 (the "License"); + * * * * * * you may not use this file except in compliance with the License. + * * * * * * You may obtain a copy of the License at + * * * * * * + * * * * * * https://www.apache.org/licenses/LICENSE-2.0 + * * * * * * + * * * * * * Unless required by applicable law or agreed to in writing, software + * * * * * * distributed under the License is distributed on an "AS IS" BASIS, + * * * * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * * * * * See the License for the specific language governing permissions and + * * * * * * limitations under the License. + * * * * * + * * * * + * * * + * * + * + */ + +package test.org.springdoc.api.v30.app244; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; +import org.springdoc.core.annotations.ParameterObject; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class HelloController { + + public record Greeting(String hi, String bye) { + } + + @PostMapping(value = "v1/greet", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) + public void endpoint(@RequestBody @ModelAttribute Greeting greeting) { + + } + + @PostMapping(value = "v2/greet") + public void endpoint2(@ParameterObject @ModelAttribute Greeting greeting) { + + } + + @PostMapping(value = "v3/greet") + @RequestBody( + content = @Content( + mediaType = MediaType.APPLICATION_FORM_URLENCODED_VALUE, + schema = @Schema(implementation = Greeting.class) + )) + public void endpoint3(Greeting greeting) { + + } + + @PostMapping(value = "v4/greet") + public void endpoint4( + @RequestBody(content = @Content( + mediaType = MediaType.APPLICATION_FORM_URLENCODED_VALUE, + schema = @Schema(implementation = Greeting.class))) + @ModelAttribute Greeting greeting) { + + } + + @PostMapping(value = "v5/greet") + @Operation( + requestBody = @RequestBody(content = @Content( + mediaType = MediaType.APPLICATION_FORM_URLENCODED_VALUE, + schema = @Schema(implementation = Greeting.class)) + )) + public void endpoint5(@ModelAttribute Greeting greeting) { + + } + +} + diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app244/SpringDocApp244Test.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app244/SpringDocApp244Test.java new file mode 100644 index 000000000..3c51cc4d1 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app244/SpringDocApp244Test.java @@ -0,0 +1,34 @@ +/* + * + * * + * * * + * * * * + * * * * * Copyright 2025 the original author or authors. + * * * * * + * * * * * Licensed under the Apache License, Version 2.0 (the "License"); + * * * * * you may not use this file except in compliance with the License. + * * * * * You may obtain a copy of the License at + * * * * * + * * * * * https://www.apache.org/licenses/LICENSE-2.0 + * * * * * + * * * * * Unless required by applicable law or agreed to in writing, software + * * * * * distributed under the License is distributed on an "AS IS" BASIS, + * * * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * * * * See the License for the specific language governing permissions and + * * * * * limitations under the License. + * * * * + * * * + * * + * + */ + +package test.org.springdoc.api.v30.app244; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import test.org.springdoc.api.v30.AbstractSpringDocV30Test; + +public class SpringDocApp244Test extends AbstractSpringDocV30Test { + + @SpringBootApplication + static class SpringDocTestApp {} +} \ No newline at end of file diff --git a/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.0.1/app244.json b/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.0.1/app244.json new file mode 100644 index 000000000..bbc136c6e --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.0.1/app244.json @@ -0,0 +1,134 @@ +{ + "openapi" : "3.0.1", + "info" : { + "title" : "OpenAPI definition", + "version" : "v0" + }, + "servers" : [ { + "url" : "http://localhost", + "description" : "Generated server url" + } ], + "paths" : { + "/v5/greet" : { + "post" : { + "tags" : [ "hello-controller" ], + "operationId" : "endpoint5", + "requestBody" : { + "content" : { + "application/x-www-form-urlencoded" : { + "schema" : { + "$ref" : "#/components/schemas/Greeting" + } + } + } + }, + "responses" : { + "200" : { + "description" : "OK" + } + } + } + }, + "/v4/greet" : { + "post" : { + "tags" : [ "hello-controller" ], + "operationId" : "endpoint4", + "requestBody" : { + "content" : { + "application/x-www-form-urlencoded" : { + "schema" : { + "$ref" : "#/components/schemas/Greeting" + } + } + } + }, + "responses" : { + "200" : { + "description" : "OK" + } + } + } + }, + "/v3/greet" : { + "post" : { + "tags" : [ "hello-controller" ], + "operationId" : "endpoint3", + "requestBody" : { + "content" : { + "application/x-www-form-urlencoded" : { + "schema" : { + "$ref" : "#/components/schemas/Greeting" + } + } + } + }, + "responses" : { + "200" : { + "description" : "OK" + } + } + } + }, + "/v2/greet" : { + "post" : { + "tags" : [ "hello-controller" ], + "operationId" : "endpoint2", + "parameters" : [ { + "name" : "hi", + "in" : "query", + "required" : false, + "schema" : { + "type" : "string" + } + }, { + "name" : "bye", + "in" : "query", + "required" : false, + "schema" : { + "type" : "string" + } + } ], + "responses" : { + "200" : { + "description" : "OK" + } + } + } + }, + "/v1/greet" : { + "post" : { + "tags" : [ "hello-controller" ], + "operationId" : "endpoint", + "requestBody" : { + "content" : { + "application/x-www-form-urlencoded" : { + "schema" : { + "$ref" : "#/components/schemas/Greeting" + } + } + } + }, + "responses" : { + "200" : { + "description" : "OK" + } + } + } + } + }, + "components" : { + "schemas" : { + "Greeting" : { + "type" : "object", + "properties" : { + "hi" : { + "type" : "string" + }, + "bye" : { + "type" : "string" + } + } + } + } + } +} \ No newline at end of file