Repository: springdoc/springdoc-openapi
Pull request #2202 (2023-04-08 19:10:01)

Support required mode v2
#2200
fixed this too #2199

for v2 PR #2201




Patch:
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/service/GenericParameterService.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/service/GenericParameterService.java
index 868e14164..32f3ec4a5 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/service/GenericParameterService.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/service/GenericParameterService.java
@@ -48,6 +48,7 @@ import io.swagger.v3.oas.annotations.enums.ParameterIn;
 import io.swagger.v3.oas.annotations.enums.ParameterStyle;
 import io.swagger.v3.oas.annotations.extensions.Extension;
 import io.swagger.v3.oas.annotations.media.ExampleObject;
+import io.swagger.v3.oas.annotations.media.Schema.RequiredMode;
 import io.swagger.v3.oas.models.Components;
 import io.swagger.v3.oas.models.examples.Example;
 import io.swagger.v3.oas.models.media.ArraySchema;
@@ -334,7 +335,7 @@ public class GenericParameterService {
 			catch (Exception e) {
 				LOGGER.warn(Constants.GRACEFUL_EXCEPTION_OCCURRED, e);
 			}
-			if (schema == null) {
+			if (schema == null && parameterDoc.array() != null) {
 				schema = AnnotationsUtils.getSchema(parameterDoc.schema(), parameterDoc.array(), true, parameterDoc.array().schema().implementation(), components, jsonView).orElse(null);
 				// default value not set by swagger-core for array !
 				if (schema != null) {
@@ -366,7 +367,7 @@ public class GenericParameterService {
 				WebConversionServiceProvider webConversionServiceProvider = optionalWebConversionServiceProvider.get();
 				if (!MethodParameterPojoExtractor.isSwaggerPrimitiveType((Class) type) && methodParameter.getParameterType().getAnnotation(io.swagger.v3.oas.annotations.media.Schema.class) == null) {
 					Class<?> springConvertedType = webConversionServiceProvider.getSpringConvertedType(methodParameter.getParameterType());
-					if (!(String.class.equals(springConvertedType) && ((Class<?>) type).isEnum()) && requestBodyInfo==null)
+					if (!(String.class.equals(springConvertedType) && ((Class<?>) type).isEnum()) && requestBodyInfo == null)
 						type = springConvertedType;
 				}
 			}
@@ -626,7 +627,9 @@ public class GenericParameterService {
 
 			@Override
 			public boolean required() {
-				return schema.required();
+				return schema.requiredMode().equals(RequiredMode.AUTO) ?
+						schema.required() :
+						schema.requiredMode().equals(RequiredMode.REQUIRED);
 			}
 
 			@Override


Test patch:
diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app206/PersonRequest.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app206/PersonRequest.java
new file mode 100644
index 000000000..747bab4a9
--- /dev/null
+++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app206/PersonRequest.java
@@ -0,0 +1,54 @@
+package test.org.springdoc.api.v30.app206;
+
+import java.util.Optional;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.media.Schema.RequiredMode;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Size;
+
+public class PersonRequest {
+	@Schema(requiredMode = RequiredMode.REQUIRED)
+	private long id;
+
+	@Schema(requiredMode = RequiredMode.NOT_REQUIRED)
+	private String firstName;
+
+	@NotBlank
+	@Size(max = 10)
+	private String lastName;
+
+	@Schema(requiredMode = RequiredMode.AUTO)
+	private Optional<String> email;
+
+	@Schema(required = true)
+	private int age;
+
+	public PersonRequest(long id, String firstName, String lastName, Optional<String> email, int age) {
+		this.id = id;
+		this.firstName = firstName;
+		this.lastName = lastName;
+		this.email = email;
+		this.age = age;
+	}
+
+	public long getId() {
+		return id;
+	}
+
+	public String getFirstName() {
+		return firstName;
+	}
+
+	public String getLastName() {
+		return lastName;
+	}
+
+	public Optional<String> getEmail() {
+		return email;
+	}
+
+	public int getAge() {
+		return age;
+	}
+}
diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app206/PersonResponse.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app206/PersonResponse.java
new file mode 100644
index 000000000..d52b42808
--- /dev/null
+++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app206/PersonResponse.java
@@ -0,0 +1,54 @@
+package test.org.springdoc.api.v30.app206;
+
+import java.util.Optional;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.media.Schema.RequiredMode;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Size;
+
+public class PersonResponse {
+	@Schema
+	private long id;
+
+	@NotBlank
+	@Size(max = 10)
+	private String firstName;
+
+	@Schema(requiredMode = RequiredMode.REQUIRED)
+	private String lastName;
+
+	@Schema(requiredMode = RequiredMode.REQUIRED)
+	private Optional<String> email;
+
+	@Schema(required = true)
+	private int age;
+
+	public PersonResponse(long id, String firstName, String lastName, Optional<String> email, int age) {
+		this.id = id;
+		this.firstName = firstName;
+		this.lastName = lastName;
+		this.email = email;
+		this.age = age;
+	}
+
+	public long getId() {
+		return id;
+	}
+
+	public String getFirstName() {
+		return firstName;
+	}
+
+	public String getLastName() {
+		return lastName;
+	}
+
+	public Optional<String> getEmail() {
+		return email;
+	}
+
+	public int getAge() {
+		return age;
+	}
+}
diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app206/RequiredModeController.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app206/RequiredModeController.java
new file mode 100644
index 000000000..1e0280282
--- /dev/null
+++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app206/RequiredModeController.java
@@ -0,0 +1,14 @@
+package test.org.springdoc.api.v30.app206;
+
+import org.springdoc.core.annotations.ParameterObject;
+
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class RequiredModeController {
+	@GetMapping
+	public PersonResponse index(@ParameterObject PersonRequest request) {
+		return null;
+	}
+}
diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app206/SpringdocApp206Test.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app206/SpringdocApp206Test.java
new file mode 100644
index 000000000..5165dcf45
--- /dev/null
+++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v30/app206/SpringdocApp206Test.java
@@ -0,0 +1,12 @@
+package test.org.springdoc.api.v30.app206;
+
+import test.org.springdoc.api.v30.AbstractSpringDocV30Test;
+
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+public class SpringdocApp206Test extends AbstractSpringDocV30Test {
+
+	@SpringBootApplication
+	static class SpringDocTestApp {}
+
+}
diff --git a/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.0.1/app206.json b/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.0.1/app206.json
new file mode 100644
index 000000000..c6f7527e5
--- /dev/null
+++ b/springdoc-openapi-starter-webmvc-api/src/test/resources/results/3.0.1/app206.json
@@ -0,0 +1,113 @@
+{
+  "openapi": "3.0.1",
+  "info": {
+    "title": "OpenAPI definition",
+    "version": "v0"
+  },
+  "servers": [
+    {
+      "url": "http://localhost",
+      "description": "Generated server url"
+    }
+  ],
+  "paths": {
+    "/": {
+      "get": {
+        "tags": [
+          "required-mode-controller"
+        ],
+        "operationId": "index",
+        "parameters": [
+          {
+            "name": "id",
+            "in": "query",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
+          },
+          {
+            "name": "firstName",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": "string"
+            }
+          },
+          {
+            "name": "lastName",
+            "in": "query",
+            "required": true,
+            "schema": {
+              "maxLength": 10,
+              "minLength": 0,
+              "type": "string"
+            }
+          },
+          {
+            "name": "email",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": "string"
+            }
+          },
+          {
+            "name": "age",
+            "in": "query",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "OK",
+            "content": {
+              "*/*": {
+                "schema": {
+                  "$ref": "#/components/schemas/PersonResponse"
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  },
+  "components": {
+    "schemas": {
+      "PersonResponse": {
+        "required": [
+          "age",
+          "email",
+          "firstName",
+          "lastName"
+        ],
+        "type": "object",
+        "properties": {
+          "id": {
+            "type": "integer",
+            "format": "int64"
+          },
+          "firstName": {
+            "maxLength": 10,
+            "minLength": 0,
+            "type": "string"
+          },
+          "lastName": {
+            "type": "string"
+          },
+          "email": {
+            "type": "string"
+          },
+          "age": {
+            "type": "integer",
+            "format": "int32"
+          }
+        }
+      }
+    }
+  }
+}