From 08ccfa66332036037545cb9c8d43300ce0f21f7b Mon Sep 17 00:00:00 2001 From: Andrew Gajda Date: Tue, 9 Sep 2025 15:50:33 -0600 Subject: [PATCH 1/2] fix: NotBlank and NotEmpty annotations follow NotNull behavior --- .../io/swagger/v3/core/jackson/ModelResolver.java | 4 ++-- .../v3/core/converting/ModelPropertyTest.java | 2 ++ .../swagger/v3/core/oas/models/RequiredFields.java | 12 ++++++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java b/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java index 8288007a42..181dd09fab 100644 --- a/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java +++ b/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java @@ -1804,7 +1804,7 @@ protected boolean applyBeanValidatorAnnotations(Schema property, Annotation[] an } } - if (annos.containsKey("javax.validation.constraints.NotEmpty")) { + if (annos.containsKey("javax.validation.constraints.NotEmpty") && applyNotNullAnnotations ) { NotEmpty anno = (NotEmpty) annos.get("javax.validation.constraints.NotEmpty"); boolean apply = checkGroupValidation(anno.groups(), invocationGroups, acceptNoGroups); if (apply) { @@ -1830,7 +1830,7 @@ protected boolean applyBeanValidatorAnnotations(Schema property, Annotation[] an } } - if (annos.containsKey("javax.validation.constraints.NotBlank")) { + if (annos.containsKey("javax.validation.constraints.NotBlank") && applyNotNullAnnotations ) { NotBlank anno = (NotBlank) annos.get("javax.validation.constraints.NotBlank"); boolean apply = checkGroupValidation(anno.groups(), invocationGroups, acceptNoGroups); if (apply) { diff --git a/modules/swagger-core/src/test/java/io/swagger/v3/core/converting/ModelPropertyTest.java b/modules/swagger-core/src/test/java/io/swagger/v3/core/converting/ModelPropertyTest.java index 4a749918ef..5a8335ed00 100644 --- a/modules/swagger-core/src/test/java/io/swagger/v3/core/converting/ModelPropertyTest.java +++ b/modules/swagger-core/src/test/java/io/swagger/v3/core/converting/ModelPropertyTest.java @@ -111,6 +111,8 @@ public void testRequiredProperty() { assertTrue(model.getRequired().contains("modeRequired")); assertFalse(model.getRequired().contains("modeNotRequired")); assertFalse(model.getRequired().contains("modeNotRequiredWithAnnotation")); + assertFalse(model.getRequired().contains("modeNotRequiredWithAnnotationForNotBlank")); + assertFalse(model.getRequired().contains("modeNotRequiredWithAnnotationForNotEmpty")); } @Test diff --git a/modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/RequiredFields.java b/modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/RequiredFields.java index 9a1cf9f8b5..c7f5d5c122 100644 --- a/modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/RequiredFields.java +++ b/modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/RequiredFields.java @@ -3,6 +3,10 @@ import io.swagger.v3.oas.annotations.media.Schema; import javax.validation.constraints.NotNull; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; + +import java.util.List; public class RequiredFields { @Schema(description = "required", required = true) @@ -31,4 +35,12 @@ public class RequiredFields { @Schema(description = "mode not required with annotation", requiredMode = Schema.RequiredMode.NOT_REQUIRED) @NotNull public Long modeNotRequiredWithAnnotation; + + @Schema(description = "mode not required with annotation for NotBlank", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + @NotBlank + public String modeNotRequiredWithAnnotationForNotBlank; + + @Schema(description = "mode not required with annotation for NotEmpty", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + @NotEmpty + public List modeNotRequiredWithAnnotationForNotEmpty; } From 8c0e1cc41103b88235d1c29a379995650cf43cf8 Mon Sep 17 00:00:00 2001 From: Ewa Ostrowska Date: Thu, 13 Nov 2025 09:08:31 +0100 Subject: [PATCH 2/2] add tests from code review --- .../v3/core/converting/ModelPropertyTest.java | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/modules/swagger-core/src/test/java/io/swagger/v3/core/converting/ModelPropertyTest.java b/modules/swagger-core/src/test/java/io/swagger/v3/core/converting/ModelPropertyTest.java index c011213509..9940234c19 100644 --- a/modules/swagger-core/src/test/java/io/swagger/v3/core/converting/ModelPropertyTest.java +++ b/modules/swagger-core/src/test/java/io/swagger/v3/core/converting/ModelPropertyTest.java @@ -15,9 +15,14 @@ import io.swagger.v3.oas.models.media.StringSchema; import org.testng.annotations.Test; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; import java.util.Date; import java.util.List; import java.util.Map; +import java.util.Set; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; @@ -141,6 +146,37 @@ public void testIssue1743() { assertEquals(is.getEnum().get(1), new Integer(2)); } + @Test + public void testNotNullWithNotBlankAndNotEmpty() { + final Map models = ModelConverters.getInstance().readAll(NotNullWithNotBlankNotEmptyModel.class); + Schema model = models.get("NotNullWithNotBlankNotEmptyModel"); + assertTrue(model.getRequired().contains("notNullAndNotBlank")); + assertTrue(model.getRequired().contains("notNullAndNotEmptyList")); + assertTrue(model.getRequired().contains("notNullAndNotEmptySet")); + } + + @Test + public void testCollectionWithNotEmpty() { + final Map models = ModelConverters.getInstance().readAll(CollectionWithNotEmptyModel.class); + Schema model = models.get("CollectionWithNotEmptyModel"); + ArraySchema listSchema = (ArraySchema) model.getProperties().get("notEmptyList"); + assertNotNull(listSchema); + assertEquals(listSchema.getMinItems(), Integer.valueOf(1)); + ArraySchema setSchema = (ArraySchema) model.getProperties().get("notEmptySet"); + assertNotNull(setSchema); + assertEquals(setSchema.getMinItems(), Integer.valueOf(1)); + } + + @Test + public void testStringWithNotBlankAndSize() { + final Map models = ModelConverters.getInstance().readAll(StringWithNotBlankAndSizeModel.class); + Schema model = models.get("StringWithNotBlankAndSizeModel"); + Schema strSchema = (Schema) model.getProperties().get("notBlankAndSized"); + assertNotNull(strSchema); + assertEquals(strSchema.getMinLength(), Integer.valueOf(5)); + assertEquals(strSchema.getMaxLength(), Integer.valueOf(10)); + } + class Family { public Date membersSince; public List members; @@ -164,4 +200,32 @@ class IsModelTest { public Boolean is_happy; public String name; } + + static class NotNullWithNotBlankNotEmptyModel { + @NotNull + @NotBlank + public String notNullAndNotBlank; + + @NotNull + @NotEmpty + public List notNullAndNotEmptyList; + + @NotNull + @NotEmpty + public Set notNullAndNotEmptySet; + } + + static class CollectionWithNotEmptyModel { + @NotEmpty + public List notEmptyList; + + @NotEmpty + public Set notEmptySet; + } + + static class StringWithNotBlankAndSizeModel { + @NotBlank + @Size(min = 5, max = 10) + public String notBlankAndSized; + } }