diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/extractor/DelegatingMethodParameter.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/extractor/DelegatingMethodParameter.java index 044f5b138..9d73b58b7 100644 --- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/extractor/DelegatingMethodParameter.java +++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/extractor/DelegatingMethodParameter.java @@ -128,21 +128,12 @@ public static MethodParameter[] customize(String[] pNames, MethodParameter[] par explodedParameters.add(methodParameter); }); } - else if (defaultFlatParamObject) { - boolean isSimpleType = MethodParameterPojoExtractor.isSimpleType(paramClass); - boolean hasAnnotation = p.hasParameterAnnotations(); - boolean shouldFlat = !isSimpleType && !hasAnnotation; - if (shouldFlat && !AbstractRequestService.isRequestTypeToIgnore(paramClass)) { - MethodParameterPojoExtractor.extractFrom(paramClass).forEach(methodParameter -> { - optionalDelegatingMethodParameterCustomizer - .ifPresent(customizer -> customizer.customize(p, methodParameter)); - explodedParameters.add(methodParameter); - }); - } - else { - String name = pNames != null ? pNames[i] : p.getParameterName(); - explodedParameters.add(new DelegatingMethodParameter(p, name, null, false, false)); - } + else if (defaultFlatParamObject && !MethodParameterPojoExtractor.isSimpleType(paramClass) && !AbstractRequestService.isRequestTypeToIgnore(paramClass)) { + MethodParameterPojoExtractor.extractFrom(paramClass).forEach(methodParameter -> { + optionalDelegatingMethodParameterCustomizer + .ifPresent(customizer -> customizer.customize(p, methodParameter)); + explodedParameters.add(methodParameter); + }); } else { String name = pNames != null ? pNames[i] : p.getParameterName(); @@ -295,4 +286,4 @@ public boolean isParameterObject() { return isParameterObject; } -} \ No newline at end of file +} diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app204/DefaultFlatParamObjectController.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app204/DefaultFlatParamObjectController.java new file mode 100644 index 000000000..1d959495f --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app204/DefaultFlatParamObjectController.java @@ -0,0 +1,14 @@ +package test.org.springdoc.api.v30.app204; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class DefaultFlatParamObjectController { + @GetMapping("/test1") + public String test1(@RequestParam String email, @Validated Person person) { + return null; + } +} diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app204/Person.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app204/Person.java new file mode 100644 index 000000000..f89ba6bd6 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app204/Person.java @@ -0,0 +1,32 @@ +package test.org.springdoc.api.v30.app204; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; + +public class Person { + private long id; + + private String firstName; + + @NotBlank + @Size(max = 10) + private String lastName; + + public Person(long id, String firstName, String lastName) { + this.id = id; + this.firstName = firstName; + this.lastName = lastName; + } + + public long getId() { + return id; + } + + public String getFirstName() { + return firstName; + } + + public String getLastName() { + return lastName; + } +} diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app204/SpringDocApp204Test.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app204/SpringDocApp204Test.java new file mode 100644 index 000000000..702eed15a --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app204/SpringDocApp204Test.java @@ -0,0 +1,34 @@ +/* + * + * * + * * * + * * * * Copyright 2019-2023 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.app204; + +import test.org.springdoc.api.v30.AbstractSpringDocV30Test; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.test.context.TestPropertySource; + +@TestPropertySource(properties = { "springdoc.default-flat-param-object=true" }) +public class SpringDocApp204Test extends AbstractSpringDocV30Test { + @SpringBootApplication + static class SpringDocTestApp {} +} diff --git a/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.0.1/app204.json b/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.0.1/app204.json new file mode 100644 index 000000000..5b31043d2 --- /dev/null +++ b/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.0.1/app204.json @@ -0,0 +1,73 @@ +{ + "openapi": "3.0.1", + "info": { + "title": "OpenAPI definition", + "version": "v0" + }, + "servers": [ + { + "url": "http://localhost", + "description": "Generated server url" + } + ], + "paths": { + "/test1": { + "get": { + "tags": [ + "default-flat-param-object-controller" + ], + "operationId": "test1", + "parameters": [ + { + "name": "email", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "id", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "firstName", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "lastName", + "in": "query", + "required": true, + "schema": { + "maxLength": 10, + "minLength": 0, + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "type": "string" + } + } + } + } + } + } + } + }, + "components": {} +} diff --git a/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/java/test/org/springdoc/api/app38/DefaultFlatParamObjectController.java b/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/java/test/org/springdoc/api/app38/DefaultFlatParamObjectController.java new file mode 100644 index 000000000..7823db61c --- /dev/null +++ b/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/java/test/org/springdoc/api/app38/DefaultFlatParamObjectController.java @@ -0,0 +1,14 @@ +package test.org.springdoc.api.app38; + +import org.springframework.data.domain.Sort; +import org.springframework.data.web.SortDefault; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class DefaultFlatParamObjectController { + @GetMapping("/test1") + public String test1(@SortDefault("name") Sort sort) { + return null; + } +} diff --git a/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/java/test/org/springdoc/api/app38/SpringDocApp38Test.java b/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/java/test/org/springdoc/api/app38/SpringDocApp38Test.java new file mode 100644 index 000000000..bb67e61fb --- /dev/null +++ b/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/java/test/org/springdoc/api/app38/SpringDocApp38Test.java @@ -0,0 +1,34 @@ +/* + * + * * Copyright 2019-2023 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.app38; + +import test.org.springdoc.api.AbstractSpringDocTest; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.test.context.TestPropertySource; + +@TestPropertySource(properties = { "springdoc.default-flat-param-object=true" }) +public class SpringDocApp38Test extends AbstractSpringDocTest { + + @SpringBootApplication + static class SpringDocTestApp { + + } + +} diff --git a/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/resources/results/app38.json b/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/resources/results/app38.json new file mode 100644 index 000000000..7f54e2d54 --- /dev/null +++ b/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/resources/results/app38.json @@ -0,0 +1,55 @@ +{ + "openapi": "3.0.1", + "info": { + "title": "OpenAPI definition", + "version": "v0" + }, + "servers": [ + { + "url": "http://localhost", + "description": "Generated server url" + } + ], + "paths": { + "/test1": { + "get": { + "tags": [ + "default-flat-param-object-controller" + ], + "operationId": "test1", + "parameters": [ + { + "name": "sort", + "in": "query", + "description": "Sorting criteria in the format: property,(asc|desc). Default sort order is ascending. Multiple sort criteria are supported.", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [ + "name,ASC" + ] + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/hal+json": { + "schema": { + "type": "string" + } + } + } + } + } + } + } + }, + "components":{ + "schemas":{} + } +}