Skip to content

Commit 9b591a5

Browse files
authored
fix: distinguish between default and example set to null and not set at all #2050 (#2286)
1 parent df3b779 commit 9b591a5

File tree

7 files changed

+1198
-9
lines changed

7 files changed

+1198
-9
lines changed

modules/swagger-parser-v2-converter/src/main/java/io/swagger/v3/parser/converter/SwaggerConverter.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -786,7 +786,9 @@ private Schema convert(SerializableParameter sp) {
786786

787787
if (sp instanceof AbstractSerializableParameter) {
788788
AbstractSerializableParameter ap = (AbstractSerializableParameter) sp;
789-
schema.setDefault(ap.getDefault());
789+
if (ap.getDefault() != null) {
790+
schema.setDefault(ap.getDefault());
791+
}
790792
}
791793
return schema;
792794
}
@@ -1163,7 +1165,9 @@ public Parameter convert(io.swagger.models.parameters.Parameter v2Parameter) {
11631165

11641166
if (sp instanceof AbstractSerializableParameter) {
11651167
AbstractSerializableParameter ap = (AbstractSerializableParameter) sp;
1166-
schema.setDefault(ap.getDefault());
1168+
if (ap.getDefault() != null) {
1169+
schema.setDefault(ap.getDefault());
1170+
}
11671171
}
11681172
}
11691173

Lines changed: 311 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,311 @@
1+
package io.swagger.parser.test;
2+
3+
import io.swagger.v3.core.util.Json;
4+
import io.swagger.v3.oas.models.OpenAPI;
5+
import io.swagger.v3.oas.models.media.Schema;
6+
import io.swagger.v3.parser.OpenAPIV3Parser;
7+
import io.swagger.v3.parser.converter.SwaggerConverter;
8+
import org.testng.annotations.Test;
9+
10+
import static org.testng.Assert.*;
11+
12+
/**
13+
* Tests for null handling in Swagger V2 to OpenAPI V3 conversion
14+
*/
15+
public class V2ConverterNullHandlingTest {
16+
17+
@Test
18+
public void testV2ParameterWithoutDefaultNotSetInV3() {
19+
String v2Yaml = "swagger: '2.0'\n" +
20+
"info:\n" +
21+
" title: Test\n" +
22+
" version: 1.0.0\n" +
23+
"paths:\n" +
24+
" /test:\n" +
25+
" get:\n" +
26+
" parameters:\n" +
27+
" - name: param1\n" +
28+
" in: query\n" +
29+
" type: string\n" +
30+
" responses:\n" +
31+
" '200':\n" +
32+
" description: OK\n";
33+
34+
OpenAPI openAPI = new SwaggerConverter().readContents(v2Yaml, null, null).getOpenAPI();
35+
assertNotNull(openAPI);
36+
System.out.println(Json.pretty(openAPI));
37+
38+
java.util.List<io.swagger.v3.oas.models.parameters.Parameter> params = openAPI.getPaths().get("/test").getGet().getParameters();
39+
assertEquals(params.size(), 1);
40+
41+
Schema schema = params.get(0).getSchema();
42+
assertNotNull(schema);
43+
assertNull(schema.getDefault(), "Default should be null");
44+
assertFalse(schema.getDefaultSetFlag(), "Default should not be set");
45+
}
46+
47+
@Test
48+
public void testV2ParameterWithDefaultPreservedInV3() {
49+
String v2Yaml = "swagger: '2.0'\n" +
50+
"info:\n" +
51+
" title: Test\n" +
52+
" version: 1.0.0\n" +
53+
"paths:\n" +
54+
" /test:\n" +
55+
" get:\n" +
56+
" parameters:\n" +
57+
" - name: param1\n" +
58+
" in: query\n" +
59+
" type: string\n" +
60+
" default: 'test'\n" +
61+
" responses:\n" +
62+
" '200':\n" +
63+
" description: OK\n";
64+
65+
OpenAPI openAPI = new SwaggerConverter().readContents(v2Yaml, null, null).getOpenAPI();
66+
assertNotNull(openAPI);
67+
System.out.println(Json.pretty(openAPI));
68+
java.util.List<io.swagger.v3.oas.models.parameters.Parameter> params = openAPI.getPaths().get("/test").getGet().getParameters();
69+
assertEquals(params.size(), 1);
70+
71+
Schema schema = params.get(0).getSchema();
72+
assertNotNull(schema);
73+
assertEquals(schema.getDefault(), "test", "Default should be 'test'");
74+
assertTrue(schema.getDefaultSetFlag(), "Default should be set");
75+
}
76+
77+
@Test
78+
public void testV2BodyParameterWithoutDefaultNotSetInV3() {
79+
String v2Yaml = "swagger: '2.0'\n" +
80+
"info:\n" +
81+
" title: Test\n" +
82+
" version: 1.0.0\n" +
83+
"paths:\n" +
84+
" /test:\n" +
85+
" post:\n" +
86+
" parameters:\n" +
87+
" - name: body\n" +
88+
" in: body\n" +
89+
" schema:\n" +
90+
" type: object\n" +
91+
" properties:\n" +
92+
" name:\n" +
93+
" type: string\n" +
94+
" responses:\n" +
95+
" '200':\n" +
96+
" description: OK\n";
97+
98+
OpenAPI openAPI = new SwaggerConverter().readContents(v2Yaml, null, null).getOpenAPI();
99+
assertNotNull(openAPI);
100+
System.out.println(Json.pretty(openAPI));
101+
102+
io.swagger.v3.oas.models.parameters.RequestBody requestBody = openAPI.getPaths().get("/test").getPost().getRequestBody();
103+
assertNotNull(requestBody);
104+
assertNotNull(requestBody.getContent());
105+
assertFalse(requestBody.getContent().isEmpty());
106+
107+
String mediaType = requestBody.getContent().containsKey("application/json") ? "application/json" : "*/*";
108+
Schema schema = requestBody.getContent().get(mediaType).getSchema();
109+
assertNotNull(schema);
110+
assertNull(schema.getDefault(), "Default should be null");
111+
assertFalse(schema.getDefaultSetFlag(), "Default should not be set");
112+
}
113+
114+
@Test
115+
public void testV2DefinitionWithoutDefaultNotSetInV3() {
116+
String v2Yaml = "swagger: '2.0'\n" +
117+
"info:\n" +
118+
" title: Test\n" +
119+
" version: 1.0.0\n" +
120+
"paths: {}\n" +
121+
"definitions:\n" +
122+
" TestModel:\n" +
123+
" type: object\n" +
124+
" properties:\n" +
125+
" name:\n" +
126+
" type: string\n";
127+
128+
OpenAPI openAPI = new SwaggerConverter().readContents(v2Yaml, null, null).getOpenAPI();
129+
assertNotNull(openAPI);
130+
System.out.println(Json.pretty(openAPI));
131+
132+
Schema schema = openAPI.getComponents().getSchemas().get("TestModel");
133+
assertNotNull(schema);
134+
assertNull(schema.getDefault(), "Default should be null");
135+
assertFalse(schema.getDefaultSetFlag(), "Default should not be set");
136+
}
137+
138+
@Test
139+
public void testV2PropertyWithDefaultPreservedInV3() {
140+
String v2Yaml = "swagger: '2.0'\n" +
141+
"info:\n" +
142+
" title: Test\n" +
143+
" version: 1.0.0\n" +
144+
"paths: {}\n" +
145+
"definitions:\n" +
146+
" TestModel:\n" +
147+
" type: object\n" +
148+
" properties:\n" +
149+
" status:\n" +
150+
" type: string\n" +
151+
" default: 'active'\n";
152+
153+
OpenAPI openAPI = new SwaggerConverter().readContents(v2Yaml, null, null).getOpenAPI();
154+
assertNotNull(openAPI);
155+
System.out.println(Json.pretty(openAPI));
156+
157+
Schema schema = openAPI.getComponents().getSchemas().get("TestModel");
158+
assertNotNull(schema);
159+
160+
Schema statusProp = (Schema) schema.getProperties().get("status");
161+
assertNotNull(statusProp);
162+
assertEquals(statusProp.getDefault(), "active", "Default should be 'active'");
163+
assertTrue(statusProp.getDefaultSetFlag(), "Default should be set");
164+
}
165+
166+
@Test
167+
public void testV2ArrayItemsWithoutDefaultNotSetInV3() {
168+
String v2Yaml = "swagger: '2.0'\n" +
169+
"info:\n" +
170+
" title: Test\n" +
171+
" version: 1.0.0\n" +
172+
"paths:\n" +
173+
" /test:\n" +
174+
" get:\n" +
175+
" parameters:\n" +
176+
" - name: items\n" +
177+
" in: query\n" +
178+
" type: array\n" +
179+
" items:\n" +
180+
" type: string\n" +
181+
" responses:\n" +
182+
" '200':\n" +
183+
" description: OK\n";
184+
185+
OpenAPI openAPI = new SwaggerConverter().readContents(v2Yaml, null, null).getOpenAPI();
186+
assertNotNull(openAPI);
187+
System.out.println(Json.pretty(openAPI));
188+
189+
java.util.List<io.swagger.v3.oas.models.parameters.Parameter> params = openAPI.getPaths().get("/test").getGet().getParameters();
190+
assertEquals(params.size(), 1);
191+
192+
Schema schema = params.get(0).getSchema();
193+
assertNotNull(schema);
194+
assertTrue(schema instanceof io.swagger.v3.oas.models.media.ArraySchema);
195+
196+
io.swagger.v3.oas.models.media.ArraySchema arraySchema =
197+
(io.swagger.v3.oas.models.media.ArraySchema) schema;
198+
assertNull(arraySchema.getDefault(), "Default should be null");
199+
assertFalse(arraySchema.getDefaultSetFlag(), "Default should not be set");
200+
}
201+
202+
@Test
203+
public void testV2ExamplePreservedInV3() {
204+
String v2Yaml = "swagger: '2.0'\n" +
205+
"info:\n" +
206+
" title: Test\n" +
207+
" version: 1.0.0\n" +
208+
"paths: {}\n" +
209+
"definitions:\n" +
210+
" TestModel:\n" +
211+
" type: object\n" +
212+
" example:\n" +
213+
" name: 'test'\n" +
214+
" properties:\n" +
215+
" name:\n" +
216+
" type: string\n";
217+
218+
OpenAPI openAPI = new SwaggerConverter().readContents(v2Yaml, null, null).getOpenAPI();
219+
assertNotNull(openAPI);
220+
221+
Schema schema = openAPI.getComponents().getSchemas().get("TestModel");
222+
assertNotNull(schema);
223+
assertNotNull(schema.getExample(), "Example should be set");
224+
}
225+
226+
@Test
227+
public void testV2PropertyWithoutExampleNotSetInV3() {
228+
String v2Yaml = "swagger: '2.0'\n" +
229+
"info:\n" +
230+
" title: Test\n" +
231+
" version: 1.0.0\n" +
232+
"paths: {}\n" +
233+
"definitions:\n" +
234+
" TestModel:\n" +
235+
" type: object\n" +
236+
" properties:\n" +
237+
" name:\n" +
238+
" type: string\n";
239+
240+
OpenAPI openAPI = new SwaggerConverter().readContents(v2Yaml, null, null).getOpenAPI();
241+
assertNotNull(openAPI);
242+
243+
Schema schema = openAPI.getComponents().getSchemas().get("TestModel");
244+
assertNotNull(schema);
245+
246+
Schema nameProp = (Schema) schema.getProperties().get("name");
247+
assertNotNull(nameProp);
248+
assertNull(nameProp.getExample(), "Example should be null");
249+
assertFalse(nameProp.getExampleSetFlag(), "Example should not be set");
250+
}
251+
252+
@Test
253+
public void testV2IntegerParameterWithDefault() {
254+
String v2Yaml = "swagger: '2.0'\n" +
255+
"info:\n" +
256+
" title: Test\n" +
257+
" version: 1.0.0\n" +
258+
"paths:\n" +
259+
" /test:\n" +
260+
" get:\n" +
261+
" parameters:\n" +
262+
" - name: limit\n" +
263+
" in: query\n" +
264+
" type: integer\n" +
265+
" default: 10\n" +
266+
" responses:\n" +
267+
" '200':\n" +
268+
" description: OK\n";
269+
270+
OpenAPI openAPI = new SwaggerConverter().readContents(v2Yaml, null, null).getOpenAPI();
271+
assertNotNull(openAPI);
272+
273+
java.util.List<io.swagger.v3.oas.models.parameters.Parameter> params = openAPI.getPaths().get("/test").getGet().getParameters();
274+
assertEquals(params.size(), 1);
275+
276+
Schema schema = params.get(0).getSchema();
277+
assertNotNull(schema);
278+
assertEquals(schema.getDefault(), 10, "Default should be 10");
279+
assertTrue(schema.getDefaultSetFlag(), "Default should be set");
280+
}
281+
282+
@Test
283+
public void testV2BooleanParameterWithDefault() {
284+
String v2Yaml = "swagger: '2.0'\n" +
285+
"info:\n" +
286+
" title: Test\n" +
287+
" version: 1.0.0\n" +
288+
"paths:\n" +
289+
" /test:\n" +
290+
" get:\n" +
291+
" parameters:\n" +
292+
" - name: verbose\n" +
293+
" in: query\n" +
294+
" type: boolean\n" +
295+
" default: false\n" +
296+
" responses:\n" +
297+
" '200':\n" +
298+
" description: OK\n";
299+
300+
OpenAPI openAPI = new SwaggerConverter().readContents(v2Yaml, null, null).getOpenAPI();
301+
assertNotNull(openAPI);
302+
303+
java.util.List<io.swagger.v3.oas.models.parameters.Parameter> params = openAPI.getPaths().get("/test").getGet().getParameters();
304+
assertEquals(params.size(), 1);
305+
306+
Schema schema = params.get(0).getSchema();
307+
assertNotNull(schema);
308+
assertEquals(schema.getDefault(), false, "Default should be false");
309+
assertTrue(schema.getDefaultSetFlag(), "Default should be set");
310+
}
311+
}

modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/OpenAPIDeserializer.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2994,8 +2994,6 @@ at the moment path passed as string (basePath) from upper components can be both
29942994
if (defaultObject != null) {
29952995
schema.setDefault(defaultObject);
29962996
}
2997-
} else {
2998-
schema.setDefault(null);
29992997
}
30002998

30012999
Map<String, Object> extensions = getExtensions(node);

modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/ResolverFully.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,10 @@ public Schema resolveSchema(Schema schema) {
437437
aggregateSchemaCombinators(composedSchema, combinedModel, composedSchema.getAnyOf(), examples, defaultValues);
438438
}
439439
if (defaultValues.size() == 1) {
440-
combinedModel.setDefault(defaultValues.iterator().next());
440+
Object defaultValue = defaultValues.iterator().next();
441+
if (defaultValue != null) {
442+
combinedModel.setDefault(defaultValue);
443+
}
441444
}
442445

443446
if (schema.getExample() != null) {
@@ -600,10 +603,11 @@ private void aggregateSchemaCombinators(ComposedSchema sourceSchema, Schema targ
600603
if (resolved.getExample() != null) {
601604
examples.add(resolved.getExample());
602605
}
603-
if (sourceSchema.getDefault() != null && resolved.getDefault() == null)
604-
defaultValues.add(sourceSchema.getDefault());
605-
else
606+
if (resolved.getDefault() != null) {
606607
defaultValues.add(resolved.getDefault());
608+
} else if (sourceSchema.getDefault() != null) {
609+
defaultValues.add(sourceSchema.getDefault());
610+
}
607611

608612
if (resolved.getExtensions() != null) {
609613
Map<String, Object> extensions = resolved.getExtensions();

0 commit comments

Comments
 (0)