Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix to remove schema duplicates when using resolveFully and then flatten #1735

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package io.swagger.v3.parser.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -102,10 +99,20 @@ private void flattenBody(String pathname, RequestBody body)
String genericName = pathBody(pathname);
if (model.getProperties() != null && model.getProperties().size() > 0) {
flattenProperties(model.getProperties(), pathname);
String modelName = resolveModelName(model.getTitle(), genericName);
mediaType.setSchema(new Schema().$ref(modelName));
addGenerated(modelName, model);
openAPI.getComponents().addSchemas(modelName, model);
if(openAPI.getComponents().getSchemas() == null ) {
createBodySchemaReference(mediaType, model, genericName);
} else if (!openAPI.getComponents().getSchemas().containsValue(model)) {
createBodySchemaReference(mediaType, model, genericName);
} else {
//Look at Components.schemas and use the reference name
String modelName = "";
for (Map.Entry<String, Schema> component : openAPI.getComponents().getSchemas().entrySet()) {
if (component.getValue().equals(model)) {
modelName = component.getKey();
}
}
mediaType.setSchema(new Schema().$ref(modelName));
}
} else if (model instanceof ComposedSchema) {
flattenComposedSchema(model, pathname);
if (model.get$ref() == null) {
Expand Down Expand Up @@ -145,6 +152,13 @@ private void flattenBody(String pathname, RequestBody body)
}
}

private void createBodySchemaReference(MediaType mediaType, Schema model, String genericName) {
String modelName = resolveModelName(model.getTitle(), genericName);
mediaType.setSchema(new Schema().$ref(modelName));
addGenerated(modelName, model);
openAPI.getComponents().addSchemas(modelName, model);
}

private void flattenParams(String pathname, List<Parameter> parameters)
{
if (parameters == null){
Expand Down Expand Up @@ -482,32 +496,20 @@ public void flattenProperties(Map<String, Schema> properties, String path) {
for (String key : properties.keySet()) {
Schema property = properties.get(key);
if (isObjectSchema(property) && property.getProperties() != null && property.getProperties().size() > 0) {
String modelName = resolveModelName(property.getTitle(), path + "_" + key);
Schema model = createModelFromProperty(property, modelName);
String existing = matchGenerated(model);
if (existing != null) {
propsToUpdate.put(key, new Schema().$ref(existing));
} else {
propsToUpdate.put(key, new Schema().$ref(RefType.SCHEMAS.getInternalPrefix()+modelName));
modelsToAdd.put(modelName, model);
addGenerated(modelName, model);
openAPI.getComponents().addSchemas(modelName, model);
if(openAPI.getComponents().getSchemas() == null){
createSchemaProperty(path, propsToUpdate, modelsToAdd, key, property);
}else if (!openAPI.getComponents().getSchemas().containsValue(property)) {
createSchemaProperty(path, propsToUpdate, modelsToAdd, key, property);
}
} else if (property instanceof ArraySchema) {
ArraySchema ap = (ArraySchema) property;
Schema inner = ap.getItems();
if (isObjectSchema(inner)) {
if (inner.getProperties() != null && inner.getProperties().size() > 0) {
flattenProperties(inner.getProperties(), path);
String modelName = resolveModelName(inner.getTitle(), path + "_" + key);
Schema innerModel = createModelFromProperty(inner, modelName);
String existing = matchGenerated(innerModel);
if (existing != null) {
ap.setItems(new Schema().$ref(existing));
} else {
ap.setItems(new Schema().$ref(modelName));
addGenerated(modelName, innerModel);
openAPI.getComponents().addSchemas(modelName, innerModel);
if(openAPI.getComponents().getSchemas() == null) {
createArraySchemaProperty(path, key, ap, inner);
}else if (!openAPI.getComponents().getSchemas().containsValue(inner)) {
createArraySchemaProperty(path, key, ap, inner);
}
}else if (inner instanceof ComposedSchema && this.flattenComposedSchemas) {
flattenComposedSchema(inner,key);
Expand Down Expand Up @@ -553,6 +555,34 @@ public void flattenProperties(Map<String, Schema> properties, String path) {
}
}

private void createArraySchemaProperty(String path, String key, ArraySchema ap, Schema inner) {
flattenProperties(inner.getProperties(), path);
String modelName = resolveModelName(inner.getTitle(), path + "_" + key);
Schema innerModel = createModelFromProperty(inner, modelName);
String existing = matchGenerated(innerModel);
if (existing != null) {
ap.setItems(new Schema().$ref(existing));
} else {
ap.setItems(new Schema().$ref(modelName));
addGenerated(modelName, innerModel);
openAPI.getComponents().addSchemas(modelName, innerModel);
}
}

private void createSchemaProperty(String path, Map<String, Schema> propsToUpdate, Map<String, Schema> modelsToAdd, String key, Schema property) {
String modelName = resolveModelName(property.getTitle(), path + "_" + key);
Schema model = createModelFromProperty(property, modelName);
String existing = matchGenerated(model);
if (existing != null) {
propsToUpdate.put(key, new Schema().$ref(existing));
} else {
propsToUpdate.put(key, new Schema().$ref(RefType.SCHEMAS.getInternalPrefix() + modelName));
modelsToAdd.put(modelName, model);
addGenerated(modelName, model);
openAPI.getComponents().addSchemas(modelName, model);
}
}

private void flattenComposedSchema(Schema inner, String key) {

ComposedSchema composedSchema = (ComposedSchema) inner;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.util.List;
import java.util.Map;

import io.swagger.v3.core.util.Yaml;
import org.testng.annotations.Test;

import io.swagger.v3.oas.models.Components;
Expand Down Expand Up @@ -48,6 +49,8 @@ public void testIssueUnexpectedNullValues() throws Exception {
assertTrue(openAPI.getComponents().getSchemas().get("verify_datasets").getExampleSetFlag());
}



@Test
public void testIssue1018() throws Exception {
ParseOptions options = new ParseOptions();
Expand Down Expand Up @@ -845,7 +848,6 @@ public void resolveInlineArrayRequestBody() throws Exception {
.requestBody(new RequestBody()
.content(new Content().addMediaType("*/*",new MediaType()
.schema(arraySchema))))));

new InlineModelResolver().flatten(openAPI);

RequestBody body = openAPI.getPaths().get("/hello").getGet().getRequestBody();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ paths:
country: CHN
provider: DataZoo
description: DataZoo China National ID

default:
description: Returns an array of errors
content:
Expand Down Expand Up @@ -110,14 +109,12 @@ paths:
country: CHN
provider: DataZoo
description: DataZoo China National ID

default:
description: Returns an array of errors
content:
application/json:
schema:
$ref: '#/components/schemas/Errors'

components:
schemas:
Dataset:
Expand Down Expand Up @@ -169,7 +166,7 @@ components:
type: object
properties:
request:
type: string
type: string
required:
- request
required:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ public SwaggerParseResult readLocation(String url, List<AuthorizationValue> auth
return output;
}
}

return output;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import io.swagger.v3.oas.models.parameters.Parameter;
import io.swagger.v3.oas.models.parameters.RequestBody;

import io.swagger.v3.parser.OpenAPIV3Parser;
import io.swagger.v3.parser.core.models.ParseOptions;
import io.swagger.v3.parser.core.models.SwaggerParseResult;
import io.swagger.v3.core.util.Json;
Expand All @@ -32,6 +33,22 @@

public class OpenAPIParserTest {

@Test
public void testIssue_1599() {
OpenAPIParser openAPIParser = new OpenAPIParser();
ParseOptions options = new ParseOptions();
options.setResolve(true);
options.setResolveFully(true);
options.setFlatten(true);
SwaggerParseResult swaggerParseResult = openAPIParser.readLocation("petStore1599.yaml", null, options);
assertNotNull(swaggerParseResult.getOpenAPI());
OpenAPI openAPI = swaggerParseResult.getOpenAPI();
assertTrue(openAPI.getComponents().getSchemas().size() == 5);
assertNull(openAPI.getComponents().getSchemas().get("pet_category"));
assertNull(openAPI.getComponents().getSchemas().get("pet_body"));
assertNull(((Schema)openAPI.getComponents().getSchemas().get("Pet").getProperties().get("category")).get$ref());
}

@Test
public void testNPE_1685() {
OpenAPIParser openAPIParser = new OpenAPIParser();
Expand Down
Loading