Skip to content

Commit c536cef

Browse files
committed
Fix behaviuor of required flag for schema class fields. Fixes #2185
1 parent 79fca7d commit c536cef

File tree

17 files changed

+150
-37
lines changed

17 files changed

+150
-37
lines changed

springdoc-openapi-common/src/main/java/org/springdoc/core/SpringDocConfiguration.java

+1
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,7 @@ SpringDocProviders springDocProviders(Optional<ActuatorProvider> actuatorProvide
420420
Optional<RepositoryRestResourceProvider> repositoryRestResourceProvider, Optional<RouterFunctionProvider> routerFunctionProvider,
421421
Optional<SpringWebProvider> springWebProvider, Optional<WebConversionServiceProvider> webConversionServiceProvider,
422422
ObjectMapperProvider objectMapperProvider) {
423+
objectMapperProvider.jsonMapper().registerModule(new SpringDocRequiredModule());
423424
return new SpringDocProviders(actuatorProvider, springCloudFunctionProvider, springSecurityOAuth2Provider, repositoryRestResourceProvider, routerFunctionProvider, springWebProvider, webConversionServiceProvider, objectMapperProvider);
424425
}
425426

springdoc-openapi-kotlin/src/main/java/org/springdoc/kotlin/SpringDocRequiredModule.java renamed to springdoc-openapi-common/src/main/java/org/springdoc/core/SpringDocRequiredModule.java

+18-7
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,20 @@
2020
*
2121
*/
2222

23-
package org.springdoc.kotlin;
23+
package org.springdoc.core;
2424

2525
import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
26-
import com.fasterxml.jackson.databind.introspect.NopAnnotationIntrospector;
2726
import com.fasterxml.jackson.databind.module.SimpleModule;
27+
import io.swagger.v3.core.jackson.SwaggerAnnotationIntrospector;
2828
import io.swagger.v3.oas.annotations.media.Schema;
29+
import org.apache.commons.lang3.StringUtils;
2930

3031
/**
3132
* The type Spring doc required module.
3233
*
3334
* @author bnasslahsen
3435
*/
35-
public class SpringDocRequiredModule extends SimpleModule {
36+
public class SpringDocRequiredModule extends SimpleModule {
3637

3738
@Override
3839
public void setupModule(SetupContext context) {
@@ -42,11 +43,21 @@ public void setupModule(SetupContext context) {
4243
/**
4344
* The type Respect schema required annotation introspector.
4445
*/
45-
private static class RespectSchemaRequiredAnnotationIntrospector extends NopAnnotationIntrospector {
46+
private static class RespectSchemaRequiredAnnotationIntrospector extends SwaggerAnnotationIntrospector {
47+
4648
@Override
47-
public Boolean hasRequiredMarker(AnnotatedMember m) {
48-
Schema schemaAnnotation = m.getAnnotation(Schema.class);
49-
return schemaAnnotation != null ? schemaAnnotation.required() : null;
49+
public Boolean hasRequiredMarker(AnnotatedMember annotatedMember) {
50+
Schema schemaAnnotation = annotatedMember.getAnnotation(Schema.class);
51+
if (schemaAnnotation != null) {
52+
Schema.RequiredMode requiredMode = schemaAnnotation.requiredMode();
53+
if (schemaAnnotation.required() || requiredMode == Schema.RequiredMode.REQUIRED) {
54+
return true;
55+
}
56+
else if (requiredMode == Schema.RequiredMode.NOT_REQUIRED || StringUtils.isNotEmpty(schemaAnnotation.defaultValue())) {
57+
return false;
58+
}
59+
}
60+
return super.hasRequiredMarker(annotatedMember);
5061
}
5162
}
5263
}

springdoc-openapi-common/src/main/java/org/springdoc/core/customizers/DataRestDelegatingMethodParameterCustomizer.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@
2424

2525
import java.lang.annotation.Annotation;
2626
import java.lang.reflect.Field;
27-
import java.util.*;
27+
import java.util.Arrays;
28+
import java.util.List;
29+
import java.util.Objects;
30+
import java.util.Optional;
2831
import java.util.regex.Pattern;
2932
import java.util.stream.Collectors;
3033

springdoc-openapi-common/src/test/java/org/springdoc/core/GenericParameterServiceTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151

5252
import org.springframework.core.MethodParameter;
5353

54-
import static org.junit.jupiter.api.Assertions.*;
54+
import static org.junit.jupiter.api.Assertions.assertEquals;
5555
import static org.mockito.ArgumentMatchers.any;
5656
import static org.mockito.Mockito.verify;
5757
import static org.mockito.Mockito.when;

springdoc-openapi-javadoc/src/test/java/org/springdoc/openapi/javadoc/JavadocPropertyCustomizerTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
import org.springdoc.core.providers.JavadocProvider;
5151
import org.springdoc.core.providers.ObjectMapperProvider;
5252

53-
import static org.junit.jupiter.api.Assertions.*;
53+
import static org.junit.jupiter.api.Assertions.assertEquals;
5454

5555
/**
5656
* Tests for {@link JavadocPropertyCustomizer}.

springdoc-openapi-kotlin/src/main/java/org/springdoc/kotlin/SpringDocKotlinConfiguration.kt

-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ class SpringDocKotlinConfiguration(objectMapperProvider: ObjectMapperProvider) {
4545
.replaceWithSchema(ByteArray::class.java, ByteArraySchema())
4646
.addDeprecatedType(Deprecated::class.java)
4747
objectMapperProvider.jsonMapper().registerModule(KotlinModule.Builder().build())
48-
objectMapperProvider.jsonMapper().registerModule(SpringDocRequiredModule())
4948
}
5049

5150
/**

springdoc-openapi-kotlin/src/test/java/test/org/springdoc/api/AbstractSpringDocTest.java

-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import java.nio.file.Paths;
2525

2626
import org.junit.jupiter.api.Test;
27-
import org.skyscreamer.jsonassert.JSONAssert;
2827
import org.slf4j.Logger;
2928
import org.slf4j.LoggerFactory;
3029
import org.springdoc.core.Constants;

springdoc-openapi-kotlin/src/test/kotlin/test/org/springdoc/api/app9/DemoController.kt

+52-4
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,56 @@ data class DemoDto(
1818
var id: Long,
1919
)
2020

21-
class DemoRequest {
22-
@field:Schema(required = false, description = "Should not be required")
23-
val nonNullableWithDefault: String = "a default value"
2421

25-
}
22+
class DemoRequest (
23+
24+
@field:Schema(required = true, defaultValue = "a default value")
25+
val requiredNullableDefault: String?,
26+
27+
@field:Schema(required = true)
28+
val requiredNullableNoDefault: String?,
29+
30+
@field:Schema(required = true, defaultValue = "a default value")
31+
val requiredNoNullableDefault: String,
32+
33+
@field:Schema(required = true)
34+
val requiredNoNullableNoDefault: String,
35+
36+
@field:Schema(requiredMode = Schema.RequiredMode.REQUIRED, defaultValue = "a default value")
37+
val requiredNullableDefault1: String?,
38+
39+
@field:Schema(requiredMode = Schema.RequiredMode.REQUIRED)
40+
val requiredNullableNoDefault1: String?,
41+
42+
@field:Schema(requiredMode = Schema.RequiredMode.REQUIRED, defaultValue = "a default value")
43+
val requiredNoNullableDefault1: String,
44+
45+
@field:Schema(requiredMode = Schema.RequiredMode.REQUIRED)
46+
val requiredNoNullableNoDefault1: String,
47+
48+
@field:Schema(requiredMode = Schema.RequiredMode.NOT_REQUIRED, defaultValue = "a default value")
49+
val noRequiredNullableDefault2: String?,
50+
51+
@field:Schema(requiredMode = Schema.RequiredMode.NOT_REQUIRED)
52+
val noRequiredNullableNoDefault2: String?,
53+
54+
@field:Schema(requiredMode = Schema.RequiredMode.NOT_REQUIRED, defaultValue = "a default value")
55+
val noRequiredNoNullableDefault2: String,
56+
57+
@field:Schema(requiredMode = Schema.RequiredMode.NOT_REQUIRED)
58+
val noRequiredNoNullableNoDefault2: String,
59+
60+
@field:Schema(defaultValue = "a default value")
61+
val noRequiredNullableDefault: String?,
62+
63+
@field:Schema
64+
val noRequiredNullableNoDefault: String?,
65+
66+
@field:Schema(defaultValue = "a default value")
67+
val noRequiredNoNullableDefault: String,
68+
69+
@field:Schema
70+
val noRequiredNoNullableNoDefault: String,
71+
72+
73+
)

springdoc-openapi-kotlin/src/test/resources/results/app9.json

+65-2
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,74 @@
4545
"components": {
4646
"schemas": {
4747
"DemoRequest": {
48+
"required": [
49+
"noRequiredNoNullableNoDefault",
50+
"requiredNoNullableDefault",
51+
"requiredNoNullableDefault1",
52+
"requiredNoNullableNoDefault",
53+
"requiredNoNullableNoDefault1",
54+
"requiredNullableDefault",
55+
"requiredNullableDefault1",
56+
"requiredNullableNoDefault",
57+
"requiredNullableNoDefault1"
58+
],
4859
"type": "object",
4960
"properties": {
50-
"nonNullableWithDefault": {
61+
"requiredNullableDefault": {
62+
"type": "string",
63+
"default": "a default value"
64+
},
65+
"requiredNullableNoDefault": {
66+
"type": "string"
67+
},
68+
"requiredNoNullableDefault": {
69+
"type": "string",
70+
"default": "a default value"
71+
},
72+
"requiredNoNullableNoDefault": {
73+
"type": "string"
74+
},
75+
"requiredNullableDefault1": {
76+
"type": "string",
77+
"default": "a default value"
78+
},
79+
"requiredNullableNoDefault1": {
80+
"type": "string"
81+
},
82+
"requiredNoNullableDefault1": {
83+
"type": "string",
84+
"default": "a default value"
85+
},
86+
"requiredNoNullableNoDefault1": {
87+
"type": "string"
88+
},
89+
"noRequiredNullableDefault2": {
90+
"type": "string",
91+
"default": "a default value"
92+
},
93+
"noRequiredNullableNoDefault2": {
94+
"type": "string"
95+
},
96+
"noRequiredNoNullableDefault2": {
97+
"type": "string",
98+
"default": "a default value"
99+
},
100+
"noRequiredNoNullableNoDefault2": {
101+
"type": "string"
102+
},
103+
"noRequiredNullableDefault": {
104+
"type": "string",
105+
"default": "a default value"
106+
},
107+
"noRequiredNullableNoDefault": {
108+
"type": "string"
109+
},
110+
"noRequiredNoNullableDefault": {
51111
"type": "string",
52-
"description": "Should not be required"
112+
"default": "a default value"
113+
},
114+
"noRequiredNoNullableNoDefault": {
115+
"type": "string"
53116
}
54117
}
55118
},

springdoc-openapi-webflux-core/src/test/java/test/org/springdoc/api/app145/SpringDocApp1452Test.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
"springdoc.use-management-port=true",
3737
"springdoc.group-configs[0].group=users",
3838
"springdoc.group-configs[0].packages-to-scan=test.org.springdoc.api.app145",
39-
"management.server.port=9066",
39+
"management.server.port=9086",
4040
"management.endpoints.web.base-path=/application" })
4141
public class SpringDocApp1452Test extends AbstractSpringDocActuatorTest {
4242

springdoc-openapi-webflux-core/src/test/java/test/org/springdoc/api/app189/HelloController.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,13 @@
2323
import io.swagger.v3.oas.annotations.media.Content;
2424
import io.swagger.v3.oas.annotations.responses.ApiResponse;
2525
import io.swagger.v3.oas.annotations.responses.ApiResponses;
26+
import reactor.core.publisher.Mono;
27+
2628
import org.springframework.http.MediaType;
2729
import org.springframework.http.codec.multipart.FilePart;
2830
import org.springframework.web.bind.annotation.PostMapping;
2931
import org.springframework.web.bind.annotation.RequestPart;
3032
import org.springframework.web.bind.annotation.RestController;
31-
import reactor.core.publisher.Mono;
3233

3334

3435
@RestController

springdoc-openapi-webflux-core/src/test/java/test/org/springdoc/api/app189/SpringDocApp189Test.java

+4-3
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,15 @@
1818

1919
package test.org.springdoc.api.app189;
2020

21+
import java.time.Duration;
22+
2123
import org.json.JSONException;
2224
import org.junit.jupiter.api.Test;
2325
import org.springdoc.core.Constants;
24-
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
25-
import org.springframework.test.web.reactive.server.EntityExchangeResult;
2626
import test.org.springdoc.api.AbstractCommonTest;
2727

28-
import java.time.Duration;
28+
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
29+
import org.springframework.test.web.reactive.server.EntityExchangeResult;
2930

3031
import static org.skyscreamer.jsonassert.JSONAssert.assertEquals;
3132

springdoc-openapi-webflux-core/src/test/java/test/org/springdoc/api/app189/SpringDocTestApp.java

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import io.swagger.v3.oas.models.info.License;
2525
import io.swagger.v3.oas.models.security.SecurityScheme;
2626
import org.springdoc.core.customizers.OpenApiCustomiser;
27+
2728
import org.springframework.boot.autoconfigure.SpringBootApplication;
2829
import org.springframework.context.annotation.Bean;
2930
import org.springframework.context.annotation.ComponentScan;

springdoc-openapi-webflux-ui/src/main/java/org/springdoc/webflux/ui/SwaggerResourceResolver.java

-2
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
package org.springdoc.webflux.ui;
22

3-
import java.io.File;
43
import java.util.List;
54

65
import org.springdoc.core.SwaggerUiConfigProperties;
76
import org.springdoc.ui.AbstractSwaggerResourceResolver;
87
import reactor.core.publisher.Mono;
98

109
import org.springframework.core.io.Resource;
11-
import org.springframework.lang.Nullable;
1210
import org.springframework.web.reactive.resource.ResourceResolver;
1311
import org.springframework.web.reactive.resource.ResourceResolverChain;
1412
import org.springframework.web.server.ServerWebExchange;

springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/v30/app204/DefaultFlatParamObjectController.java

-2
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,9 @@
33
import org.springdoc.api.annotations.ParameterObject;
44

55
import org.springframework.data.domain.Sort;
6-
import org.springframework.data.domain.Sort.Direction;
76
import org.springframework.data.web.SortDefault;
87
import org.springframework.validation.annotation.Validated;
98
import org.springframework.web.bind.annotation.GetMapping;
10-
import org.springframework.web.bind.annotation.RequestMapping;
119
import org.springframework.web.bind.annotation.RequestParam;
1210
import org.springframework.web.bind.annotation.RestController;
1311

springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/v30/app204/Person.java

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package test.org.springdoc.api.v30.app204;
22

33
import javax.validation.constraints.NotBlank;
4-
import javax.validation.constraints.NotNull;
54
import javax.validation.constraints.Size;
65

76
public class Person {

springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/v30/app204/SpringDocApp204Test.java

-9
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,11 @@
2222

2323
package test.org.springdoc.api.v30.app204;
2424

25-
import org.junit.jupiter.api.Test;
26-
import org.springdoc.core.Constants;
2725
import test.org.springdoc.api.v30.AbstractSpringDocV30Test;
2826

2927
import org.springframework.boot.autoconfigure.SpringBootApplication;
30-
import org.springframework.context.annotation.Import;
3128
import org.springframework.test.context.TestPropertySource;
3229

33-
import static org.hamcrest.Matchers.is;
34-
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
35-
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
36-
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
37-
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
38-
3930
@TestPropertySource(properties = { "springdoc.default-flat-param-object=true" })
4031
public class SpringDocApp204Test extends AbstractSpringDocV30Test {
4132
@SpringBootApplication

0 commit comments

Comments
 (0)