From edbac9443007cd60dac456499b8ece30fb0f120e Mon Sep 17 00:00:00 2001 From: gracekarina Date: Sat, 18 Nov 2017 21:54:35 -0500 Subject: [PATCH 1/2] fixing issue and adding test - oneOf Items --- .../v3/parser/util/OpenAPIDeserializer.java | 12 +- .../swagger/v3/parser/util/ResolverFully.java | 7 +- .../v3/parser/test/OpenAPIResolverTest.java | 23 +++- .../src/test/resources/oneof-anyof.yaml | 82 ++++++++++++ .../src/test/resources/definitions.yaml | 37 ++++++ .../src/test/resources/spec.yaml | 120 ++++++++++++++++++ 6 files changed, 275 insertions(+), 6 deletions(-) create mode 100644 modules/swagger-parser-v3/src/test/resources/oneof-anyof.yaml create mode 100644 modules/swagger-parser/src/test/resources/definitions.yaml create mode 100644 modules/swagger-parser/src/test/resources/spec.yaml diff --git a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/OpenAPIDeserializer.java b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/OpenAPIDeserializer.java index 167f7cddba..f354d07aec 100644 --- a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/OpenAPIDeserializer.java +++ b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/OpenAPIDeserializer.java @@ -1817,10 +1817,16 @@ public Schema getSchema(ObjectNode node, String location, ParseResult result){ schema = oneOfList; } else if(itemsNode != null) { ArraySchema items = new ArraySchema(); - for(JsonNode n : itemsNode) { - if(n.isValueNode()) { - items.setItems(getSchema(itemsNode, location, result)); + if (itemsNode.getNodeType().equals(JsonNodeType.OBJECT)){ + items.setItems(getSchema(itemsNode, location, result)); + }else if (itemsNode.getNodeType().equals(JsonNodeType.ARRAY)){ + for (JsonNode n : itemsNode) { + if (n.isValueNode()) { + items.setItems(getSchema(itemsNode, location, result)); + } } + + } schema = items; } else { diff --git a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/ResolverFully.java b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/ResolverFully.java index fabaffdbd4..69519b8ba2 100644 --- a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/ResolverFully.java +++ b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/ResolverFully.java @@ -165,8 +165,11 @@ public Schema resolveSchema(Schema schema) { if(schema instanceof ArraySchema) { ArraySchema arrayModel = (ArraySchema) schema; - if(arrayModel.getItems().get$ref() != null) { - arrayModel.setItems(resolveSchema(arrayModel.getItems())); + if(arrayModel.getItems() != null){ + arrayModel.setItems(arrayModel.getItems()); + if(arrayModel.getItems().get$ref() != null) { + arrayModel.setItems(resolveSchema(arrayModel.getItems())); + } } return arrayModel; } diff --git a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIResolverTest.java b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIResolverTest.java index 5ed1db97c5..863481081f 100644 --- a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIResolverTest.java +++ b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIResolverTest.java @@ -572,7 +572,6 @@ public void resolveComposedReferenceSchema(@Injectable final List auths){ + + + + ParseOptions options = new ParseOptions(); + options.setResolve(true); + options.setResolveFully(true); + + OpenAPI openAPI = new OpenAPIV3Parser().readLocation("src/test/resources/oneof-anyof.yaml",auths,options).getOpenAPI(); + + ResolverFully resolverUtil = new ResolverFully(); + resolverUtil.resolveFully(openAPI); + + assertTrue(openAPI.getPaths().get("/mixed-array").getGet().getResponses().get("200").getContent().get("application/json").getSchema() instanceof ArraySchema); + ArraySchema arraySchema = (ArraySchema) openAPI.getPaths().get("/mixed-array").getGet().getResponses().get("200").getContent().get("application/json").getSchema(); + assertTrue(arraySchema.getItems() instanceof ComposedSchema); + ComposedSchema oneOf = (ComposedSchema) arraySchema.getItems(); + assertEquals(oneOf.getOneOf().get(0).getType(), "string"); + + } + private static int getDynamicPort() { return new Random().ints(50000, 60000).findFirst().getAsInt(); } diff --git a/modules/swagger-parser-v3/src/test/resources/oneof-anyof.yaml b/modules/swagger-parser-v3/src/test/resources/oneof-anyof.yaml new file mode 100644 index 0000000000..9506d2017e --- /dev/null +++ b/modules/swagger-parser-v3/src/test/resources/oneof-anyof.yaml @@ -0,0 +1,82 @@ +openapi: 3.0.0 +info: + version: 0.0.0 + title: test + +paths: + /oneOf: + get: + responses: + '200': + description: A book or movie object + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/Book' + - $ref: '#/components/schemas/Movie' + + /anyOf: + get: + responses: + '200': + description: A book or movie object + content: + application/json: + schema: + anyOf: + - $ref: '#/components/schemas/Movie' + - $ref: '#/components/schemas/Book' + + /mixed-array: + get: + responses: + '200': + description: An array containing strings and/or integers + content: + application/json: + schema: + type: array + items: + oneOf: + - type: string + - type: integer + +components: + schemas: + Book: + type: object + properties: + title: + type: string + authors: + type: array + items: + type: string + isbn: + type: string + required: + - title + example: + title: The Hitchhiker's Guide to the Galaxy + authors: + - Douglas Adams + isbn: 0-330-25864-8 + Movie: + type: object + properties: + title: + type: string + directors: + type: array + items: + type: string + year: + type: integer + required: + - title + example: + title: Blade Runner + directors: + - Ridley Scott + year: 1982 \ No newline at end of file diff --git a/modules/swagger-parser/src/test/resources/definitions.yaml b/modules/swagger-parser/src/test/resources/definitions.yaml new file mode 100644 index 0000000000..51efd7cbe0 --- /dev/null +++ b/modules/swagger-parser/src/test/resources/definitions.yaml @@ -0,0 +1,37 @@ +definitions: + pet: + type: object + required: + - id + - name + properties: + id: + type: integer + format: int64 + name: + type: string + tag: + type: string + newPet: + type: object + required: + - name + properties: + id: + type: integer + format: int64 + name: + type: string + tag: + type: string + errorModel: + type: object + required: + - code + - message + properties: + code: + type: integer + format: int32 + message: + type: string \ No newline at end of file diff --git a/modules/swagger-parser/src/test/resources/spec.yaml b/modules/swagger-parser/src/test/resources/spec.yaml new file mode 100644 index 0000000000..d56d1d6131 --- /dev/null +++ b/modules/swagger-parser/src/test/resources/spec.yaml @@ -0,0 +1,120 @@ +swagger: '2.0' +info: + version: '1.0.0' + title: Swagger Petstore (Simple) + description: A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification + termsOfService: http://helloreverb.com/terms/ + contact: + name: Swagger API team + email: foo@example.com + url: http://swagger.io + license: + name: MIT + url: http://opensource.org/licenses/MIT +host: petstore.swagger.io +basePath: /api +schemes: + - http +consumes: + - application/json +produces: + - application/json +paths: + /pets: + get: + description: Returns all pets from the system that the user has access to + operationId: findPets + produces: + - application/json + - application/xml + - text/xml + - text/html + parameters: + - name: tags + in: query + description: tags to filter by + required: false + type: array + items: + type: string + collectionFormat: csv + - name: limit + in: query + description: maximum number of results to return + required: false + type: integer + format: int32 + responses: + '200': + description: pet response + schema: + type: array + items: + $ref: '/definitions.yaml#/definitions/pet' + default: + description: unexpected error + schema: + $ref: '/definitions.yaml#/definitions/errorModel' + post: + description: Creates a new pet in the store. Duplicates are allowed + operationId: addPet + produces: + - application/json + parameters: + - name: pet + in: body + description: Pet to add to the store + required: true + schema: + $ref: '/definitions.yaml#/definitions/newPet' + responses: + '200': + description: pet response + schema: + $ref: '/definitions.yaml#/definitions/pet' + default: + description: unexpected error + schema: + $ref: '/definitions.yaml#/definitions/errorModel' + /pets/{id}: + get: + description: Returns a user based on a single ID, if the user does not have access to the pet + operationId: findPetById + produces: + - application/json + - application/xml + - text/xml + - text/html + parameters: + - name: id + in: path + description: ID of pet to fetch + required: true + type: integer + format: int64 + responses: + '200': + description: pet response + schema: + $ref: '/definitions.yaml#/definitions/pet' + default: + description: unexpected error + schema: + $ref: '/definitions.yaml#/definitions/errorModel' + delete: + description: deletes a single pet based on the ID supplied + operationId: deletePet + parameters: + - name: id + in: path + description: ID of pet to delete + required: true + type: integer + format: int64 + responses: + '204': + description: pet deleted + default: + description: unexpected error + schema: + $ref: '/definitions.yaml#/definitions/errorModel' \ No newline at end of file From 724e5ca7e4c34023f8e5f5f66ee52f165e939a2c Mon Sep 17 00:00:00 2001 From: gracekarina Date: Mon, 20 Nov 2017 09:11:02 -0500 Subject: [PATCH 2/2] resolving anyof-oneof --- .../v3/parser/util/OpenAPIDeserializer.java | 2 - .../swagger/v3/parser/util/ResolverFully.java | 75 +++++++------------ .../v3/parser/test/OpenAPIResolverTest.java | 18 ++--- 3 files changed, 38 insertions(+), 57 deletions(-) diff --git a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/OpenAPIDeserializer.java b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/OpenAPIDeserializer.java index f354d07aec..de430f1988 100644 --- a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/OpenAPIDeserializer.java +++ b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/OpenAPIDeserializer.java @@ -1825,8 +1825,6 @@ public Schema getSchema(ObjectNode node, String location, ParseResult result){ items.setItems(getSchema(itemsNode, location, result)); } } - - } schema = items; } else { diff --git a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/ResolverFully.java b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/ResolverFully.java index 69519b8ba2..00c7dfd4a7 100644 --- a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/ResolverFully.java +++ b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/ResolverFully.java @@ -19,6 +19,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; @@ -165,12 +166,12 @@ public Schema resolveSchema(Schema schema) { if(schema instanceof ArraySchema) { ArraySchema arrayModel = (ArraySchema) schema; - if(arrayModel.getItems() != null){ + if(arrayModel.getItems().get$ref() != null) { + arrayModel.setItems(resolveSchema(arrayModel.getItems())); + } else { arrayModel.setItems(arrayModel.getItems()); - if(arrayModel.getItems().get$ref() != null) { - arrayModel.setItems(resolveSchema(arrayModel.getItems())); - } } + return arrayModel; } if (schema instanceof ObjectSchema) { @@ -213,57 +214,39 @@ public Schema resolveSchema(Schema schema) { } } } + if (requiredProperties.size() > 0) { + model.setRequired(new ArrayList<>(requiredProperties)); + } + if (composedSchema.getExtensions() != null) { + Map extensions = composedSchema.getExtensions(); + for (String key : extensions.keySet()) { + model.addExtension(key, composedSchema.getExtensions().get(key)); + } + } + return model; } + } else if (composedSchema.getOneOf() != null) { + Schema resolved; + List list = new ArrayList<>(); for (Schema innerModel : composedSchema.getOneOf()) { - Schema resolved = resolveSchema(innerModel); - Map properties = resolved.getProperties(); - if (resolved.getProperties() != null) { - - for (String key : properties.keySet()) { - Schema prop = (Schema) resolved.getProperties().get(key); - model.addProperties(key, resolveSchema(prop)); - } - if (resolved.getRequired() != null) { - for (int i = 0; i < resolved.getRequired().size(); i++) { - if (resolved.getRequired().get(i) != null) { - requiredProperties.add(resolved.getRequired().get(i).toString()); - } - } - } - } + resolved = resolveSchema(innerModel); + list.add(resolved); } + composedSchema.setOneOf(list); } else if (composedSchema.getAnyOf() != null) { + Schema resolved; + List list = new ArrayList<>(); for (Schema innerModel : composedSchema.getAnyOf()) { - Schema resolved = resolveSchema(innerModel); - Map properties = resolved.getProperties(); - if (resolved.getProperties() != null) { - - for (String key : properties.keySet()) { - Schema prop = (Schema) resolved.getProperties().get(key); - model.addProperties(key, resolveSchema(prop)); - } - if (resolved.getRequired() != null) { - for (int i = 0; i < resolved.getRequired().size(); i++) { - if (resolved.getRequired().get(i) != null) { - requiredProperties.add(resolved.getRequired().get(i).toString()); - } - } - } - } + resolved = resolveSchema(innerModel); + list.add(resolved); } + composedSchema.setAnyOf(list); } - if (requiredProperties.size() > 0) { - model.setRequired(new ArrayList<>(requiredProperties)); - } - if (composedSchema.getExtensions() != null) { - Map extensions = composedSchema.getExtensions(); - for (String key : extensions.keySet()) { - model.addExtension(key, composedSchema.getExtensions().get(key)); - } - } - return model; + + + return composedSchema; } else { // User don't want to aggregate composed schema, we only solve refs if (composedSchema.getAllOf() != null) diff --git a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIResolverTest.java b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIResolverTest.java index 863481081f..159d56c49c 100644 --- a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIResolverTest.java +++ b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIResolverTest.java @@ -563,7 +563,7 @@ public void resolveAllOfWithoutAggregatingParameters(@Injectable final List auths){ + public void resolveComposedReferenceAllOfSchema(@Injectable final List auths){ @@ -572,11 +572,11 @@ public void resolveComposedReferenceSchema(@Injectable final List auths){ - - ParseOptions options = new ParseOptions(); - options.setResolve(true); + //options.setResolveCombinators(false); options.setResolveFully(true); - OpenAPI openAPI = new OpenAPIV3Parser().readLocation("src/test/resources/oneof-anyof.yaml",auths,options).getOpenAPI(); - ResolverFully resolverUtil = new ResolverFully(); - resolverUtil.resolveFully(openAPI); assertTrue(openAPI.getPaths().get("/mixed-array").getGet().getResponses().get("200").getContent().get("application/json").getSchema() instanceof ArraySchema); ArraySchema arraySchema = (ArraySchema) openAPI.getPaths().get("/mixed-array").getGet().getResponses().get("200").getContent().get("application/json").getSchema(); @@ -601,6 +596,11 @@ public void resolveComposedSchema(@Injectable final List aut ComposedSchema oneOf = (ComposedSchema) arraySchema.getItems(); assertEquals(oneOf.getOneOf().get(0).getType(), "string"); + //System.out.println(openAPI.getPaths().get("/oneOf").getGet().getResponses().get("200").getContent().get("application/json").getSchema() ); + assertTrue(openAPI.getPaths().get("/oneOf").getGet().getResponses().get("200").getContent().get("application/json").getSchema() instanceof ComposedSchema); + ComposedSchema oneOfSchema = (ComposedSchema) openAPI.getPaths().get("/oneOf").getGet().getResponses().get("200").getContent().get("application/json").getSchema(); + assertEquals(oneOfSchema.getOneOf().get(0).getType(), "object"); + } private static int getDynamicPort() {