From 121d9ec4e9eeaae0dc86723f3d030f9b0b7f9d7a Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Sun, 9 Apr 2023 03:33:06 +0900 Subject: [PATCH 1/2] Fix Schema get condition of ArraySchema. Fixes #2199 --- .../main/java/org/springdoc/core/GenericParameterService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/springdoc-openapi-common/src/main/java/org/springdoc/core/GenericParameterService.java b/springdoc-openapi-common/src/main/java/org/springdoc/core/GenericParameterService.java index fac8c2e7f..fdba684da 100644 --- a/springdoc-openapi-common/src/main/java/org/springdoc/core/GenericParameterService.java +++ b/springdoc-openapi-common/src/main/java/org/springdoc/core/GenericParameterService.java @@ -326,7 +326,7 @@ private void setSchema(io.swagger.v3.oas.annotations.Parameter parameterDoc, Com 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) { @@ -358,7 +358,7 @@ Schema calculateSchema(Components components, ParameterInfo parameterInfo, Reque 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; } } From 823cac2ff39570d295e6c24af1fc0fa6ad06d3fa Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Sat, 8 Apr 2023 17:17:35 +0900 Subject: [PATCH 2/2] Support schema.requiredMode() on ParameterObject. #2200 --- .../core/GenericParameterService.java | 5 +- .../api/v30/app206/PersonRequest.java | 59 +++++++++ .../api/v30/app206/PersonResponse.java | 55 +++++++++ .../v30/app206/RequiredModeController.java | 14 +++ .../api/v30/app206/SpringdocApp206Test.java | 12 ++ .../test/resources/results/3.0.1/app206.json | 113 ++++++++++++++++++ 6 files changed, 257 insertions(+), 1 deletion(-) create mode 100644 springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/v30/app206/PersonRequest.java create mode 100644 springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/v30/app206/PersonResponse.java create mode 100644 springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/v30/app206/RequiredModeController.java create mode 100644 springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/v30/app206/SpringdocApp206Test.java create mode 100644 springdoc-openapi-webmvc-core/src/test/resources/results/3.0.1/app206.json diff --git a/springdoc-openapi-common/src/main/java/org/springdoc/core/GenericParameterService.java b/springdoc-openapi-common/src/main/java/org/springdoc/core/GenericParameterService.java index fdba684da..d0b081453 100644 --- a/springdoc-openapi-common/src/main/java/org/springdoc/core/GenericParameterService.java +++ b/springdoc-openapi-common/src/main/java/org/springdoc/core/GenericParameterService.java @@ -46,6 +46,7 @@ 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; @@ -619,7 +620,9 @@ public String description() { @Override public boolean required() { - return schema.required(); + return schema.requiredMode().equals(RequiredMode.AUTO) ? + schema.required() : + schema.requiredMode().equals(RequiredMode.REQUIRED); } @Override diff --git a/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/v30/app206/PersonRequest.java b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/v30/app206/PersonRequest.java new file mode 100644 index 000000000..fa2867aa6 --- /dev/null +++ b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/v30/app206/PersonRequest.java @@ -0,0 +1,59 @@ +package test.org.springdoc.api.v30.app206; + +import java.util.Optional; + +import javax.validation.constraints.Email; +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; + +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.media.Schema.RequiredMode; + +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 email; + + @Schema(required = true) + private int age; + + public PersonRequest(long id, String firstName, String lastName, Optional 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 getEmail() { + return email; + } + + public int getAge() { + return age; + } +} diff --git a/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/v30/app206/PersonResponse.java b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/v30/app206/PersonResponse.java new file mode 100644 index 000000000..42ad1ae12 --- /dev/null +++ b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/v30/app206/PersonResponse.java @@ -0,0 +1,55 @@ +package test.org.springdoc.api.v30.app206; + +import java.util.Optional; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.media.Schema.RequiredMode; + +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 email; + + @Schema(required = true) + private int age; + + public PersonResponse(long id, String firstName, String lastName, Optional 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 getEmail() { + return email; + } + + public int getAge() { + return age; + } +} diff --git a/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/v30/app206/RequiredModeController.java b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/v30/app206/RequiredModeController.java new file mode 100644 index 000000000..df887ecac --- /dev/null +++ b/springdoc-openapi-webmvc-core/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.api.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-webmvc-core/src/test/java/test/org/springdoc/api/v30/app206/SpringdocApp206Test.java b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/v30/app206/SpringdocApp206Test.java new file mode 100644 index 000000000..5165dcf45 --- /dev/null +++ b/springdoc-openapi-webmvc-core/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-webmvc-core/src/test/resources/results/3.0.1/app206.json b/springdoc-openapi-webmvc-core/src/test/resources/results/3.0.1/app206.json new file mode 100644 index 000000000..c6f7527e5 --- /dev/null +++ b/springdoc-openapi-webmvc-core/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" + } + } + } + } + } +}