Skip to content

Commit d5c3728

Browse files
committed
refs #4474 - fix NPE while resolving container types
1 parent 194b1dd commit d5c3728

File tree

3 files changed

+177
-8
lines changed

3 files changed

+177
-8
lines changed

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

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
import io.swagger.v3.core.util.AnnotationsUtils;
3535
import io.swagger.v3.core.util.Constants;
3636
import io.swagger.v3.core.util.Json;
37-
import io.swagger.v3.core.util.Json31;
3837
import io.swagger.v3.core.util.ObjectMapperFactory;
3938
import io.swagger.v3.core.util.ReferenceTypeUtils;
4039
import io.swagger.v3.core.util.PrimitiveType;
@@ -438,7 +437,7 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context
438437

439438

440439
if (keyType != null && valueType != null) {
441-
if (ReflectionUtils.isSystemType(type) && !annotatedType.isSchemaProperty() && !annotatedType.isResolveAsRef()) {
440+
if (ReflectionUtils.isSystemTypeNotArray(type) && !annotatedType.isSchemaProperty() && !annotatedType.isResolveAsRef()) {
442441
context.resolve(new AnnotatedType().components(annotatedType.getComponents()).type(valueType).jsonViewAnnotation(annotatedType.getJsonViewAnnotation()));
443442
return null;
444443
}
@@ -470,7 +469,7 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context
470469
mapModel.name(name);
471470
model = mapModel;
472471
} else if (valueType != null) {
473-
if (ReflectionUtils.isSystemType(type) && !annotatedType.isSchemaProperty() && !annotatedType.isResolveAsRef()) {
472+
if (ReflectionUtils.isSystemTypeNotArray(type) && !annotatedType.isSchemaProperty() && !annotatedType.isResolveAsRef()) {
474473
context.resolve(new AnnotatedType().components(annotatedType.getComponents()).type(valueType).jsonViewAnnotation(annotatedType.getJsonViewAnnotation()));
475474
return null;
476475
}
@@ -924,10 +923,12 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context
924923
.collect(Collectors.toList());
925924
anyOfFiltered.forEach(c -> {
926925
Schema anyOfRef = context.resolve(new AnnotatedType().components(annotatedType.getComponents()).type(c).jsonViewAnnotation(annotatedType.getJsonViewAnnotation()));
927-
if (StringUtils.isNotBlank(anyOfRef.getName())) {
928-
composedSchema.addAnyOfItem(new Schema().$ref(Components.COMPONENTS_SCHEMAS_REF + anyOfRef.getName()));
929-
} else {
930-
composedSchema.addAnyOfItem(anyOfRef);
926+
if (anyOfRef != null) {
927+
if (StringUtils.isNotBlank(anyOfRef.getName())) {
928+
composedSchema.addAnyOfItem(new Schema().$ref(Components.COMPONENTS_SCHEMAS_REF + anyOfRef.getName()));
929+
} else {
930+
composedSchema.addAnyOfItem(anyOfRef);
931+
}
931932
}
932933
// remove shared properties defined in the parent
933934
if (isSubtype(beanDesc.getClassInfo(), c)) {

modules/swagger-core/src/main/java/io/swagger/v3/core/util/ReflectionUtils.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,10 @@ public static boolean isVoid(Type type) {
440440
}
441441

442442
public static boolean isSystemType(JavaType type) {
443+
return isSystemTypeNotArray(type) ? true : type.isArrayType();
444+
}
445+
446+
public static boolean isSystemTypeNotArray(JavaType type) {
443447
// used while resolving container types to skip resolving system types; possibly extend by checking classloader
444448
// and/or other packages
445449
for (String systemPrefix: PrimitiveType.systemPrefixes()) {
@@ -450,7 +454,7 @@ public static boolean isSystemType(JavaType type) {
450454
}
451455
}
452456
}
453-
return type.isArrayType();
457+
return false;
454458
}
455459

456460
/**
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
package io.swagger.v3.core.resolving;
2+
3+
import io.swagger.v3.core.converter.AnnotatedType;
4+
import io.swagger.v3.core.converter.ModelConverterContextImpl;
5+
import io.swagger.v3.core.jackson.ModelResolver;
6+
import io.swagger.v3.core.matchers.SerializationMatchers;
7+
import io.swagger.v3.oas.models.media.Schema;
8+
import org.testng.annotations.AfterMethod;
9+
import org.testng.annotations.Test;
10+
11+
import java.util.ArrayList;
12+
import java.util.HashMap;
13+
import java.util.List;
14+
import java.util.Map;
15+
16+
public class Ticket4474Test extends SwaggerTestBase {
17+
18+
@AfterMethod
19+
public void afterTest() {
20+
ModelResolver.enumsAsRef = false;
21+
}
22+
23+
@Test
24+
public void testAnyOf() throws Exception {
25+
ModelResolver.enumsAsRef = true;
26+
27+
final ModelResolver modelResolver = new ModelResolver(mapper());
28+
29+
final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver);
30+
31+
final Schema model = context
32+
.resolve(new AnnotatedType(Document.class));
33+
34+
SerializationMatchers.assertEqualsToYaml(context.getDefinedModels(), "Document:\n" +
35+
" type: object\n" +
36+
" properties:\n" +
37+
" data:\n" +
38+
" type: object\n" +
39+
" additionalProperties:\n" +
40+
" type: object\n" +
41+
" anyOf:\n" +
42+
" - type: array\n" +
43+
" items:\n" +
44+
" type: boolean\n" +
45+
" - type: array\n" +
46+
" items:\n" +
47+
" type: integer\n" +
48+
" format: int32\n" +
49+
" - type: array\n" +
50+
" items:\n" +
51+
" type: integer\n" +
52+
" format: int64\n" +
53+
" - type: array\n" +
54+
" items:\n" +
55+
" type: number\n" +
56+
" format: double\n" +
57+
" - type: array\n" +
58+
" items:\n" +
59+
" type: string\n" +
60+
" - type: boolean\n" +
61+
" - type: integer\n" +
62+
" format: int32\n" +
63+
" - type: integer\n" +
64+
" format: int64\n" +
65+
" listData:\n" +
66+
" type: array\n" +
67+
" items:\n" +
68+
" type: object\n" +
69+
" anyOf:\n" +
70+
" - type: array\n" +
71+
" items:\n" +
72+
" type: boolean\n" +
73+
" - type: array\n" +
74+
" items:\n" +
75+
" type: integer\n" +
76+
" format: int32\n" +
77+
" - type: array\n" +
78+
" items:\n" +
79+
" type: integer\n" +
80+
" format: int64\n" +
81+
" - type: array\n" +
82+
" items:\n" +
83+
" type: number\n" +
84+
" format: double\n" +
85+
" - type: array\n" +
86+
" items:\n" +
87+
" type: string\n" +
88+
" - type: boolean\n" +
89+
" - type: integer\n" +
90+
" format: int32\n" +
91+
" - type: integer\n" +
92+
" format: int64\n" +
93+
" itemData:\n" +
94+
" type: object\n" +
95+
" anyOf:\n" +
96+
" - type: array\n" +
97+
" items:\n" +
98+
" type: boolean\n" +
99+
" - type: array\n" +
100+
" items:\n" +
101+
" type: integer\n" +
102+
" format: int32\n" +
103+
" - type: array\n" +
104+
" items:\n" +
105+
" type: integer\n" +
106+
" format: int64\n" +
107+
" - type: array\n" +
108+
" items:\n" +
109+
" type: number\n" +
110+
" format: double\n" +
111+
" - type: array\n" +
112+
" items:\n" +
113+
" type: string\n" +
114+
" - type: boolean\n" +
115+
" - type: integer\n" +
116+
" format: int32\n" +
117+
" - type: integer\n" +
118+
" format: int64");
119+
}
120+
121+
static class Document {
122+
@io.swagger.v3.oas.annotations.media.Schema(
123+
anyOf = {
124+
Boolean[].class,
125+
Integer[].class,
126+
Long[].class,
127+
Double[].class,
128+
String[].class,
129+
Boolean.class,
130+
Integer.class,
131+
Long.class,
132+
Map.class,
133+
})
134+
public Map<String, Object> data = new HashMap<>();
135+
136+
@io.swagger.v3.oas.annotations.media.Schema(
137+
anyOf = {
138+
Boolean[].class,
139+
Integer[].class,
140+
Long[].class,
141+
Double[].class,
142+
String[].class,
143+
Boolean.class,
144+
Integer.class,
145+
Long.class,
146+
Map.class,
147+
})
148+
public List<Object> listData = new ArrayList<>();
149+
150+
@io.swagger.v3.oas.annotations.media.Schema(
151+
anyOf = {
152+
Boolean[].class,
153+
Integer[].class,
154+
Long[].class,
155+
Double[].class,
156+
String[].class,
157+
Boolean.class,
158+
Integer.class,
159+
Long.class,
160+
Map.class,
161+
})
162+
public Object itemData = new Object();
163+
}
164+
}

0 commit comments

Comments
 (0)