From 6027e7364a399224d67dc9623b6330fbd78fcb62 Mon Sep 17 00:00:00 2001 From: chimmi <3124852+chimmi@users.noreply.github.com> Date: Sat, 30 Mar 2024 15:11:00 +0300 Subject: [PATCH 1/2] Issue 2071. Correctly handle external refs in array items composed schemas --- .../processors/ExternalRefProcessor.java | 71 +++++++++++-------- .../processors/ExternalRefProcessorTest.java | 20 ++++++ .../resources/issue-2071/definitions.yaml | 25 +++++++ .../test/resources/issue-2071/openapi.yaml | 21 ++++++ 4 files changed, 106 insertions(+), 31 deletions(-) create mode 100644 modules/swagger-parser-v3/src/test/resources/issue-2071/definitions.yaml create mode 100644 modules/swagger-parser-v3/src/test/resources/issue-2071/openapi.yaml diff --git a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/ExternalRefProcessor.java b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/ExternalRefProcessor.java index c62f5ef771..de955cef71 100644 --- a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/ExternalRefProcessor.java +++ b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/ExternalRefProcessor.java @@ -147,36 +147,7 @@ public String processRefToExternalSchema(String $ref, RefFormat refFormat) { if(schema instanceof ComposedSchema){ ComposedSchema composedSchema = (ComposedSchema) schema; - if (composedSchema.getAllOf() != null){ - for(Schema item : composedSchema.getAllOf()){ - if (item.get$ref() != null){ - processRefSchema(item,file); - } else{ - processSchema(item, file); - } - } - - }if (composedSchema.getOneOf() != null){ - for(Schema item : composedSchema.getOneOf()){ - if (item.get$ref() != null){ - if (item.get$ref() != null){ - processRefSchema(item,file); - }else{ - processSchema(item, file); - } - } - } - }if (composedSchema.getAnyOf() != null){ - for(Schema item : composedSchema.getAnyOf()){ - if (item.get$ref() != null){ - if (item.get$ref() != null){ - processRefSchema(item,file); - }else{ - processSchema(item, file); - } - } - } - } + processComposedSchema(composedSchema, file); } //Loop the properties and recursively call this method; Map subProps = schema.getProperties(); @@ -212,14 +183,52 @@ public String processRefToExternalSchema(String $ref, RefFormat refFormat) { ArraySchema arraySchema = (ArraySchema) schema; if (StringUtils.isNotBlank(arraySchema.getItems().get$ref())) { processRefSchema(((ArraySchema) schema).getItems(), file); + } else if (arraySchema.getItems() instanceof ComposedSchema) { + ComposedSchema composedSchema = (ComposedSchema) arraySchema.getItems(); + processComposedSchema(composedSchema, file); } else { - processProperties(arraySchema.getItems().getProperties() ,file); + processProperties(arraySchema.getItems().getProperties(), file); } } } return newRef; } + private void processComposedSchema(ComposedSchema composedSchema, String file) { + if (composedSchema.getAllOf() != null) { + for (Schema item : composedSchema.getAllOf()) { + if (item.get$ref() != null) { + processRefSchema(item, file); + } else { + processSchema(item, file); + } + } + + } + if (composedSchema.getOneOf() != null) { + for (Schema item : composedSchema.getOneOf()) { + if (item.get$ref() != null) { + if (item.get$ref() != null) { + processRefSchema(item, file); + } else { + processSchema(item, file); + } + } + } + } + if (composedSchema.getAnyOf() != null) { + for (Schema item : composedSchema.getAnyOf()) { + if (item.get$ref() != null) { + if (item.get$ref() != null) { + processRefSchema(item, file); + } else { + processSchema(item, file); + } + } + } + } + } + private void processSchema(Schema property, String file) { if (property != null) { if (StringUtils.isNotBlank(property.get$ref())) { diff --git a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/processors/ExternalRefProcessorTest.java b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/processors/ExternalRefProcessorTest.java index 218f97571a..b83feee3e4 100644 --- a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/processors/ExternalRefProcessorTest.java +++ b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/processors/ExternalRefProcessorTest.java @@ -5,14 +5,18 @@ import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.StringSchema; +import io.swagger.v3.parser.OpenAPIV3Parser; import io.swagger.v3.parser.ResolverCache; import io.swagger.v3.parser.core.models.AuthorizationValue; +import io.swagger.v3.parser.core.models.ParseOptions; +import io.swagger.v3.parser.core.models.SwaggerParseResult; import io.swagger.v3.parser.models.RefFormat; import io.swagger.v3.parser.util.RemoteUrl; import mockit.Expectations; import mockit.Injectable; import mockit.Mocked; import mockit.Expectations; +import org.testng.Assert; import org.testng.annotations.Test; import java.util.ArrayList; @@ -23,6 +27,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; import static org.testng.Assert.assertEquals; @@ -206,4 +211,19 @@ public void testRelativeRefIncludingUrlRef() is("./relative-with-url/relative-with-local.yaml#/relative-same-file") ); } + + @Test + public void testHandleComposedSchemasInArrayItems() { + OpenAPIV3Parser openApiParser = new OpenAPIV3Parser(); + ParseOptions options = new ParseOptions(); + options.setResolve(true); + SwaggerParseResult parseResult = openApiParser.readLocation("issue-2071/openapi.yaml", null, options); + OpenAPI openAPI = parseResult.getOpenAPI(); + + assertEquals(openAPI.getComponents().getSchemas().size(), 3); + assertTrue(openAPI.getComponents().getSchemas().containsKey("Response")); + assertTrue(openAPI.getComponents().getSchemas().containsKey("ProductRow")); + assertTrue(openAPI.getComponents().getSchemas().containsKey("ProductsRowType")); + } + } diff --git a/modules/swagger-parser-v3/src/test/resources/issue-2071/definitions.yaml b/modules/swagger-parser-v3/src/test/resources/issue-2071/definitions.yaml new file mode 100644 index 0000000000..25a85f75b5 --- /dev/null +++ b/modules/swagger-parser-v3/src/test/resources/issue-2071/definitions.yaml @@ -0,0 +1,25 @@ +components: + schemas: + Response: + type: array + items: + oneOf: + - $ref: '#/components/schemas/ProductRow' + discriminator: + propertyName: type + mapping: + 'product': '#/components/schemas/ProductRow' + ProductRow: + type: object + additionalProperties: false + required: + - type + properties: + type: + $ref: '#/components/schemas/ProductsRowType' + payload: + type: string + ProductsRowType: + type: string + enum: + - product diff --git a/modules/swagger-parser-v3/src/test/resources/issue-2071/openapi.yaml b/modules/swagger-parser-v3/src/test/resources/issue-2071/openapi.yaml new file mode 100644 index 0000000000..d457a1dd94 --- /dev/null +++ b/modules/swagger-parser-v3/src/test/resources/issue-2071/openapi.yaml @@ -0,0 +1,21 @@ +openapi: 3.0.1 +info: + title: API + description: API + version: LATEST +paths: + /test-path: + post: + requestBody: + required: true + content: + text/plain: + schema: + type: string + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: 'definitions.yaml#/components/schemas/Response' From dc8953b02407e742d8072b561c7ee05db1f2e297 Mon Sep 17 00:00:00 2001 From: chimmi <3124852+chimmi@users.noreply.github.com> Date: Thu, 4 Apr 2024 00:09:21 +0300 Subject: [PATCH 2/2] Issue 2071. Correctly handle external refs in array items composed schemas --- .../processors/ExternalRefProcessor.java | 7 ++++--- .../processors/ExternalRefProcessorTest.java | 11 ++++++---- .../resources/issue-2071/definitions.yaml | 21 +++++++++++++++++-- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/ExternalRefProcessor.java b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/ExternalRefProcessor.java index de955cef71..0413f79312 100644 --- a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/ExternalRefProcessor.java +++ b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/ExternalRefProcessor.java @@ -183,10 +183,11 @@ public String processRefToExternalSchema(String $ref, RefFormat refFormat) { ArraySchema arraySchema = (ArraySchema) schema; if (StringUtils.isNotBlank(arraySchema.getItems().get$ref())) { processRefSchema(((ArraySchema) schema).getItems(), file); - } else if (arraySchema.getItems() instanceof ComposedSchema) { - ComposedSchema composedSchema = (ComposedSchema) arraySchema.getItems(); - processComposedSchema(composedSchema, file); } else { + if (arraySchema.getItems() instanceof ComposedSchema) { + ComposedSchema composedSchema = (ComposedSchema) arraySchema.getItems(); + processComposedSchema(composedSchema, file); + } processProperties(arraySchema.getItems().getProperties(), file); } } diff --git a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/processors/ExternalRefProcessorTest.java b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/processors/ExternalRefProcessorTest.java index b83feee3e4..267591ad0c 100644 --- a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/processors/ExternalRefProcessorTest.java +++ b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/processors/ExternalRefProcessorTest.java @@ -220,10 +220,13 @@ public void testHandleComposedSchemasInArrayItems() { SwaggerParseResult parseResult = openApiParser.readLocation("issue-2071/openapi.yaml", null, options); OpenAPI openAPI = parseResult.getOpenAPI(); - assertEquals(openAPI.getComponents().getSchemas().size(), 3); - assertTrue(openAPI.getComponents().getSchemas().containsKey("Response")); - assertTrue(openAPI.getComponents().getSchemas().containsKey("ProductRow")); - assertTrue(openAPI.getComponents().getSchemas().containsKey("ProductsRowType")); + Map components = openAPI.getComponents().getSchemas(); + assertEquals(components.size(), 5); + assertTrue(components.containsKey("Response")); + assertTrue(components.containsKey("ProductRow")); + assertTrue(components.containsKey("ProductRowType")); + assertTrue(components.containsKey("OrderRow")); + assertTrue(components.containsKey("OrderRowType")); } } diff --git a/modules/swagger-parser-v3/src/test/resources/issue-2071/definitions.yaml b/modules/swagger-parser-v3/src/test/resources/issue-2071/definitions.yaml index 25a85f75b5..3d0068dfb0 100644 --- a/modules/swagger-parser-v3/src/test/resources/issue-2071/definitions.yaml +++ b/modules/swagger-parser-v3/src/test/resources/issue-2071/definitions.yaml @@ -5,6 +5,9 @@ components: items: oneOf: - $ref: '#/components/schemas/ProductRow' + properties: + orderRow: + $ref: '#/components/schemas/OrderRow' discriminator: propertyName: type mapping: @@ -16,10 +19,24 @@ components: - type properties: type: - $ref: '#/components/schemas/ProductsRowType' + $ref: '#/components/schemas/ProductRowType' payload: type: string - ProductsRowType: + ProductRowType: type: string enum: - product + OrderRow: + type: object + additionalProperties: false + required: + - type + properties: + type: + $ref: '#/components/schemas/OrderRowType' + payload: + type: string + OrderRowType: + type: string + enum: + - order