Skip to content

Commit 7e6faf8

Browse files
authored
Merge pull request #1276 from swagger-api/flattenComposedSchemas_v3
flattenComposedSchema Option - refs - #1275
2 parents 26bcac1 + fd31168 commit 7e6faf8

File tree

5 files changed

+222
-15
lines changed

5 files changed

+222
-15
lines changed

modules/swagger-parser-core/src/main/java/io/swagger/v3/parser/core/models/ParseOptions.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ public class ParseOptions {
55
private boolean resolveCombinators = true;
66
private boolean resolveFully;
77
private boolean flatten;
8+
private boolean flattenComposedSchemas;
89
private boolean skipMatches;
910

1011
public boolean isResolve() {
@@ -42,4 +43,12 @@ public boolean isSkipMatches() {
4243
public void setSkipMatches(boolean skipMatches) {
4344
this.skipMatches = skipMatches;
4445
}
46+
47+
public boolean isFlattenComposedSchemas() {
48+
return flattenComposedSchemas;
49+
}
50+
51+
public void setFlattenComposedSchemas(boolean flattenComposedSchemas) {
52+
this.flattenComposedSchemas = flattenComposedSchemas;
53+
}
4554
}

modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/OpenAPIV3Parser.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public SwaggerParseResult readLocation(String url, List<AuthorizationValue> auth
7070
result.setOpenAPI(resolver.resolve());
7171
new ResolverFully(options.isResolveCombinators()).resolveFully(result.getOpenAPI());
7272
} else if (options.isFlatten()) {
73-
InlineModelResolver inlineModelResolver = new InlineModelResolver();
73+
InlineModelResolver inlineModelResolver = new InlineModelResolver(options.isFlattenComposedSchemas());
7474
inlineModelResolver.setSkipMatches(options.isSkipMatches());
7575
inlineModelResolver.flatten(result.getOpenAPI());
7676
}
@@ -207,7 +207,7 @@ public SwaggerParseResult readContents(String swaggerAsString, List<Authorizatio
207207
result.setOpenAPI(new OpenAPIResolver(result.getOpenAPI(), auth, null).resolve());
208208
new ResolverFully(options.isResolveCombinators()).resolveFully(result.getOpenAPI());
209209
} else if (options.isFlatten()) {
210-
InlineModelResolver inlineModelResolver = new InlineModelResolver();
210+
InlineModelResolver inlineModelResolver = new InlineModelResolver(options.isFlattenComposedSchemas());
211211
inlineModelResolver.setSkipMatches(options.isSkipMatches());
212212
inlineModelResolver.flatten(result.getOpenAPI());
213213
}

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

Lines changed: 65 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,15 @@ public class InlineModelResolver {
3232
Map<String, Schema> addedModels = new HashMap<>();
3333
Map<String, String> generatedSignature = new HashMap<>();
3434

35+
private boolean flattenComposedSchemas;
36+
37+
38+
public InlineModelResolver(){this(false);}
39+
40+
public InlineModelResolver(boolean flattenComposedSchemas) {
41+
this.flattenComposedSchemas = flattenComposedSchemas;
42+
}
43+
3544
public void flatten(OpenAPI openAPI) {
3645
this.openAPI = openAPI;
3746

@@ -359,6 +368,32 @@ public void flattenProperties(Map<String, Schema> properties, String path) {
359368
if (inner.getProperties() != null && inner.getProperties().size() > 0) {
360369
flattenProperties(inner.getProperties(), path);
361370
String modelName = resolveModelName(inner.getTitle(), path + "_" + key);
371+
Schema innerModel = createModelFromProperty(inner, modelName);
372+
String existing = matchGenerated(innerModel);
373+
if (existing != null) {
374+
ap.setItems(new Schema().$ref(existing));
375+
} else {
376+
ap.setItems(new Schema().$ref(modelName));
377+
addGenerated(modelName, innerModel);
378+
openAPI.getComponents().addSchemas(modelName, innerModel);
379+
}
380+
}else if(inner instanceof ComposedSchema && this.flattenComposedSchemas){
381+
ComposedSchema composedSchema = (ComposedSchema) inner;
382+
String modelName = resolveModelName(inner.getTitle(), path + "_" + key);
383+
List<Schema> list = null;
384+
if (composedSchema.getAllOf() != null) {
385+
list = composedSchema.getAllOf();
386+
}else if (composedSchema.getAnyOf() != null) {
387+
list = composedSchema.getAnyOf();
388+
}else if (composedSchema.getOneOf() != null) {
389+
list = composedSchema.getOneOf();
390+
}
391+
for(int i= 0; i<list.size();i++){
392+
if(list.get(i).getProperties()!= null){
393+
flattenProperties(list.get(i).getProperties(), modelName);
394+
}
395+
}
396+
362397
Schema innerModel = createModelFromProperty(inner, modelName);
363398
String existing = matchGenerated(innerModel);
364399
if (existing != null) {
@@ -369,6 +404,7 @@ public void flattenProperties(Map<String, Schema> properties, String path) {
369404
openAPI.getComponents().addSchemas(modelName, innerModel);
370405
}
371406
}
407+
372408
}
373409
} else if (property.getAdditionalProperties() != null && property.getAdditionalProperties() instanceof Schema) {
374410
Schema inner = (Schema) property.getAdditionalProperties();
@@ -437,20 +473,36 @@ public Schema createModelFromProperty(Schema schema, String path) {
437473
XML xml = schema.getXml();
438474
Map<String, Schema> properties = schema.getProperties();
439475

440-
Schema model = new Schema();//TODO Verify this!
441-
model.setDescription(description);
442-
model.setExample(example);
443-
model.setName(name);
444-
model.setXml(xml);
445-
model.setType(schema.getType());
446-
model.setRequired(requiredList);
447-
448-
if (properties != null) {
449-
flattenProperties(properties, path);
450-
model.setProperties(properties);
451-
}
452476

453-
return model;
477+
if (schema instanceof ComposedSchema && this.flattenComposedSchemas){
478+
ComposedSchema composedModel = (ComposedSchema) schema;
479+
480+
composedModel.setDescription(description);
481+
composedModel.setExample(example);
482+
composedModel.setName(name);
483+
composedModel.setXml(xml);
484+
composedModel.setType(schema.getType());
485+
composedModel.setRequired(requiredList);
486+
487+
return composedModel;
488+
489+
490+
} else {
491+
Schema model = new Schema();//TODO Verify this!
492+
model.setDescription(description);
493+
model.setExample(example);
494+
model.setName(name);
495+
model.setXml(xml);
496+
model.setType(schema.getType());
497+
model.setRequired(requiredList);
498+
499+
if (properties != null) {
500+
flattenProperties(properties, path);
501+
model.setProperties(properties);
502+
}
503+
504+
return model;
505+
}
454506
}
455507

456508
@SuppressWarnings("static-method")

modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIV3ParserTest.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,37 @@ public class OpenAPIV3ParserTest {
6666
protected int serverPort = getDynamicPort();
6767
protected WireMockServer wireMockServer;
6868

69+
70+
@Test
71+
public void testFlattenComposedSchema() {
72+
OpenAPIV3Parser openApiParser = new OpenAPIV3Parser();
73+
ParseOptions options = new ParseOptions();
74+
options.setResolve(true);
75+
options.setFlatten(true);
76+
options.setFlattenComposedSchemas(true);
77+
SwaggerParseResult parseResult = openApiParser.readLocation("flattenComposedSchemaComplete.json", null, options);
78+
79+
OpenAPI openAPI = parseResult.getOpenAPI();
80+
assertNotNull(openAPI.getComponents().getSchemas().get("val_Members_val_member"));
81+
assertNotNull(openAPI.getComponents().getSchemas().get("val_MemberProducts_val_product"));
82+
83+
}
84+
85+
@Test
86+
public void testNotFlattenComposedSchema() {
87+
OpenAPIV3Parser openApiParser = new OpenAPIV3Parser();
88+
ParseOptions options = new ParseOptions();
89+
options.setResolve(true);
90+
options.setFlatten(true);
91+
92+
SwaggerParseResult parseResult = openApiParser.readLocation("flattenComposedSchemaComplete.json", null, options);
93+
94+
OpenAPI openAPI = parseResult.getOpenAPI();
95+
assertNull(openAPI.getComponents().getSchemas().get("val_Members_val_member"));
96+
assertNotNull(openAPI.getComponents().getSchemas().get("val_MemberProducts_val_product"));
97+
98+
}
99+
69100
@Test
70101
public void testCodegenIssue8601() {
71102
OpenAPIV3Parser openApiParser = new OpenAPIV3Parser();
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
{
2+
"openapi": "3.0.2",
3+
"info": {
4+
"title": "test",
5+
"version": "1.0.0"
6+
},
7+
"paths": {
8+
"/validation": {
9+
"post": {
10+
"tags": [
11+
"mytag"
12+
],
13+
"summary": "summary",
14+
"requestBody": {
15+
"required": true,
16+
"content": {
17+
"application/json": {
18+
"schema": {
19+
"$ref": "#/components/schemas/mtg_Message"
20+
}
21+
}
22+
}
23+
},
24+
"responses": {
25+
"200": {
26+
"description": "desc",
27+
"content": {
28+
"application/json": {
29+
"schema": {
30+
"$ref": "#/components/schemas/mtg_Message"
31+
}
32+
}
33+
}
34+
}
35+
}
36+
}
37+
}
38+
},
39+
"components": {
40+
"schemas": {
41+
"mtg_Message": {
42+
"type": "object"
43+
},
44+
"val_MemberProducts": {
45+
"additionalProperties": false,
46+
"description": "val_MemberProducts desc",
47+
"properties": {
48+
"val_product": {
49+
"items": {
50+
"type": "object",
51+
"properties": {
52+
"val_unique_reference1": {
53+
"type": "string"
54+
}
55+
}
56+
},
57+
"maxItems": 4,
58+
"minItems": 1,
59+
"type": "array"
60+
}
61+
},
62+
"required": [
63+
"val_product"
64+
],
65+
"type": "object"
66+
},
67+
"val_Members": {
68+
"additionalProperties": false,
69+
"description": "valmembers desc",
70+
"properties": {
71+
"val_member": {
72+
"description": "valmember desc",
73+
"items": {
74+
"type": "object",
75+
"oneOf": [
76+
{
77+
"$ref": "#/components/schemas/val_MemberChoice1"
78+
},
79+
{
80+
"$ref": "#/components/schemas/val_MemberChoice2"
81+
}
82+
]
83+
},
84+
"minItems": 1,
85+
"type": "array"
86+
}
87+
},
88+
"required": [
89+
"val_member"
90+
],
91+
"type": "object"
92+
},
93+
"val_MemberChoice1": {
94+
"additionalProperties": false,
95+
"description": "val_MemberChoice1 desc",
96+
"properties": {
97+
"val_unique_reference1": {
98+
"type": "string"
99+
}
100+
},
101+
"type": "object"
102+
},
103+
"val_MemberChoice2": {
104+
"additionalProperties": false,
105+
"description": "val_MemberChoice2 desc",
106+
"properties": {
107+
"val_unique_reference2": {
108+
"type": "string"
109+
}
110+
},
111+
"type": "object"
112+
}
113+
}
114+
}
115+
}

0 commit comments

Comments
 (0)