Repository: springdoc/springdoc-openapi
Pull request #2184 (2023-03-30 15:18:01)

fixed DefaultFlatParamObject to work with annotated parameters. Fixes…
#2181

please see PR: #2183
for 2.x branch


Patch:
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 class DelegatingMethodParameter extends MethodParameter {
 					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 class DelegatingMethodParameter extends MethodParameter {
 		return isParameterObject;
 	}
 
-}
\ No newline at end of file
+}


Test patch:
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":{}
+  }
+}