Skip to content

Commit dd98ce0

Browse files
committed
refs-#4703/#4702-Fix applyBeanValidatorAnnotations method to support both OAS 3.1/3.0
1 parent 290c78d commit dd98ce0

File tree

2 files changed

+146
-23
lines changed

2 files changed

+146
-23
lines changed

modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1511,43 +1511,38 @@ protected void applyBeanValidatorAnnotations(Schema property, Annotation[] annot
15111511
if ("integer".equals(property.getType()) || "number".equals(property.getType())) {
15121512
property.setMinimum(new BigDecimal(size.min()));
15131513
property.setMaximum(new BigDecimal(size.max()));
1514-
} else if (property instanceof StringSchema) {
1515-
StringSchema sp = (StringSchema) property;
1516-
sp.minLength(Integer.valueOf(size.min()));
1517-
sp.maxLength(Integer.valueOf(size.max()));
1518-
} else if (property instanceof ArraySchema) {
1519-
ArraySchema sp = (ArraySchema) property;
1520-
sp.setMinItems(size.min());
1521-
sp.setMaxItems(size.max());
1514+
}
1515+
if (isStringSchema(property)) {
1516+
property.setMinLength(Integer.valueOf(size.min()));
1517+
property.setMaxLength(Integer.valueOf(size.max()));
1518+
}
1519+
if (isArraySchema(property)) {
1520+
property.setMinItems(size.min());
1521+
property.setMaxItems(size.max());
15221522
}
15231523
}
15241524
if (annos.containsKey("javax.validation.constraints.DecimalMin")) {
15251525
DecimalMin min = (DecimalMin) annos.get("javax.validation.constraints.DecimalMin");
1526-
if (property instanceof NumberSchema) {
1527-
NumberSchema ap = (NumberSchema) property;
1528-
ap.setMinimum(new BigDecimal(min.value()));
1529-
ap.setExclusiveMinimum(!min.inclusive());
1526+
if (isNumberSchema(property)) {
1527+
property.setMinimum(new BigDecimal(min.value()));
1528+
property.setExclusiveMinimum(!min.inclusive());
15301529
}
15311530
}
15321531
if (annos.containsKey("javax.validation.constraints.DecimalMax")) {
15331532
DecimalMax max = (DecimalMax) annos.get("javax.validation.constraints.DecimalMax");
1534-
if (property instanceof NumberSchema) {
1535-
NumberSchema ap = (NumberSchema) property;
1536-
ap.setMaximum(new BigDecimal(max.value()));
1537-
ap.setExclusiveMaximum(!max.inclusive());
1533+
if (isNumberSchema(property)) {
1534+
property.setMaximum(new BigDecimal(max.value()));
1535+
property.setExclusiveMaximum(!max.inclusive());
15381536
}
15391537
}
15401538
if (annos.containsKey("javax.validation.constraints.Pattern")) {
15411539
Pattern pattern = (Pattern) annos.get("javax.validation.constraints.Pattern");
1542-
1543-
if (property instanceof StringSchema) {
1540+
if (isStringSchema(property)) {
15441541
property.setPattern(pattern.regexp());
15451542
}
1546-
1547-
if(property.getItems() != null && property.getItems() instanceof StringSchema) {
1543+
if(property.getItems() != null && isStringSchema(property.getItems())) {
15481544
property.getItems().setPattern(pattern.regexp());
15491545
}
1550-
15511546
}
15521547
}
15531548

@@ -3009,6 +3004,18 @@ protected boolean isObjectSchema(Schema schema) {
30093004
return (schema.getTypes() != null && schema.getTypes().contains("object")) || "object".equals(schema.getType()) || (schema.getType() == null && schema.getProperties() != null && !schema.getProperties().isEmpty());
30103005
}
30113006

3007+
protected boolean isArraySchema(Schema schema){
3008+
return "array".equals(schema.getType()) || (schema.getTypes() != null && schema.getTypes().contains("array"));
3009+
}
3010+
3011+
protected boolean isStringSchema(Schema schema){
3012+
return "string".equals(schema.getType()) || (schema.getTypes() != null && schema.getTypes().contains("string"));
3013+
}
3014+
3015+
protected boolean isNumberSchema(Schema schema){
3016+
return "number".equals(schema.getType()) || (schema.getTypes() != null && schema.getTypes().contains("number"));
3017+
}
3018+
30123019
protected Schema buildRefSchemaIfObject(Schema schema, ModelConverterContext context) {
30133020
if (schema == null) {
30143021
return null;

modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/ModelResolverOAS31Test.java

Lines changed: 118 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import io.swagger.v3.core.converter.AnnotatedType;
44
import io.swagger.v3.core.converter.ModelConverterContextImpl;
5+
import io.swagger.v3.core.converter.ModelConverters;
56
import io.swagger.v3.core.jackson.ModelResolver;
67
import io.swagger.v3.core.matchers.SerializationMatchers;
78
import io.swagger.v3.core.resolving.SwaggerTestBase;
@@ -10,10 +11,14 @@
1011
import io.swagger.v3.core.resolving.v31.model.AnnotatedArray;
1112
import io.swagger.v3.core.resolving.v31.model.ModelWithDependentSchema;
1213
import io.swagger.v3.core.resolving.v31.model.ModelWithOAS31Stuff;
13-
import io.swagger.v3.core.resolving.v31.model.ModelWithOAS31StuffMinimal;
14-
import io.swagger.v3.core.util.Yaml31;
1514
import io.swagger.v3.oas.models.media.Schema;
1615
import org.testng.annotations.Test;
16+
import javax.validation.constraints.DecimalMax;
17+
import javax.validation.constraints.DecimalMin;
18+
import javax.validation.constraints.Pattern;
19+
import javax.validation.constraints.Size;
20+
import java.util.List;
21+
import java.util.Map;
1722

1823
public class ModelResolverOAS31Test extends SwaggerTestBase {
1924

@@ -231,4 +236,115 @@ public void testFieldArraySchemaAnnotation() {
231236
" type: string\n" +
232237
" maxItems: 10");
233238
}
239+
240+
@Test(description = "@Pattern correctly handled in type parameters of properties using collections when using oas 3.1.0")
241+
public void testModelUsingCollectionTypePropertyHandlesPatternAnnotationForOas31() {
242+
String expectedYaml = "ClassWithUsingPatternOnCollection:\n" +
243+
" type: object\n" +
244+
" properties:\n" +
245+
" myField:\n" +
246+
" type: array\n" +
247+
" items:\n" +
248+
" pattern: myPattern\n" +
249+
" type: string";
250+
251+
Map<String, Schema> stringSchemaMap = ModelConverters.getInstance(true).readAll(ClassWithUsingPatternOnCollection.class);
252+
SerializationMatchers.assertEqualsToYaml31(stringSchemaMap, expectedYaml);
253+
}
254+
255+
private static class ClassWithUsingPatternOnCollection {
256+
private List<@Pattern(regexp = "myPattern") String> myField;
257+
258+
public List<String> getMyField() {
259+
return myField;
260+
}
261+
262+
public void setMyField(List<String> myField) {
263+
this.myField = myField;
264+
}
265+
}
266+
267+
@Test(description = "@Size correctly handled in properties using collections when using oas 3.1.0")
268+
public void testModelUsingCollectionTypePropertyHandleSizeAnnotationForOas31() {
269+
String expectedYaml = "ClassWithUsingSizeOnCollection:\n" +
270+
" type: object\n" +
271+
" properties:\n" +
272+
" myField:\n" +
273+
" maxItems: 100\n" +
274+
" minItems: 1\n" +
275+
" type: array\n" +
276+
" items:\n" +
277+
" type: string";
278+
279+
Map<String, io.swagger.v3.oas.models.media.Schema> stringSchemaMap = ModelConverters.getInstance(true).readAll(ClassWithUsingSizeOnCollection.class);
280+
SerializationMatchers.assertEqualsToYaml31(stringSchemaMap, expectedYaml);
281+
}
282+
283+
private static class ClassWithUsingSizeOnCollection {
284+
@Size(min = 1, max = 100)
285+
private List<String> myField;
286+
287+
public List<String> getMyField() {
288+
return myField;
289+
}
290+
291+
public void setMyField(List<String> myField) {
292+
this.myField = myField;
293+
}
294+
}
295+
296+
@Test(description = "@Size correctly handled for field type String using OAS 3.1.0")
297+
public void testSizeAnnotationOnFieldForOAS31() {
298+
String expectedYaml = "ClassWithUsingSizeOnField:\n" +
299+
" type: object\n" +
300+
" properties:\n" +
301+
" myField:\n" +
302+
" type: string\n" +
303+
" maxLength: 100\n" +
304+
" minLength: 1";
305+
306+
Map<String, io.swagger.v3.oas.models.media.Schema> stringSchemaMap = ModelConverters.getInstance(true).readAll(ClassWithUsingSizeOnField.class);
307+
SerializationMatchers.assertEqualsToYaml31(stringSchemaMap, expectedYaml);
308+
}
309+
310+
private static class ClassWithUsingSizeOnField {
311+
@Size(min = 1, max = 100)
312+
private String myField;
313+
314+
public String getMyField() {
315+
return myField;
316+
}
317+
318+
public void setMyField(String myField) {
319+
this.myField = myField;
320+
}
321+
}
322+
323+
@Test(description = "@DecimalMax/Min annotations correctly handled for field type Number using OAS 3.1.0")
324+
public void testDecimalAnnotationsOnField() {
325+
String expectedYaml = "ClassWithUsingDecimalAnnotationsOnField:\n" +
326+
" type: object\n" +
327+
" properties:\n" +
328+
" myField:\n" +
329+
" type: number\n" +
330+
" maximum: 100\n" +
331+
" minimum: 1";
332+
333+
Map<String, io.swagger.v3.oas.models.media.Schema> stringSchemaMap = ModelConverters.getInstance(true).readAll(ClassWithUsingDecimalAnnotationsOnField.class);
334+
SerializationMatchers.assertEqualsToYaml31(stringSchemaMap, expectedYaml);
335+
}
336+
337+
private static class ClassWithUsingDecimalAnnotationsOnField {
338+
@DecimalMin("1")
339+
@DecimalMax("100")
340+
private Number myField;
341+
342+
public Number getMyField() {
343+
return myField;
344+
}
345+
346+
public void setMyField(Number myField) {
347+
this.myField = myField;
348+
}
349+
}
234350
}

0 commit comments

Comments
 (0)