Repository: swagger-api/swagger-parser
Pull request #1846 (2022-11-02 15:40:02)

fix: refs #1801, #1821 - fix OAS 3.1 type(s) processing


Patch:
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 e5ae493f..fbcd77b0 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
@@ -13,6 +13,7 @@ import io.swagger.v3.oas.models.OpenAPI;
 import io.swagger.v3.oas.models.Operation;
 import io.swagger.v3.oas.models.PathItem;
 import io.swagger.v3.oas.models.Paths;
+import io.swagger.v3.oas.models.SpecVersion;
 import io.swagger.v3.oas.models.callbacks.Callback;
 import io.swagger.v3.oas.models.examples.Example;
 import io.swagger.v3.oas.models.links.Link;
@@ -313,6 +314,7 @@ public class OpenAPIDeserializer {
 				return null;
 			} else if (value.startsWith("3.1")) {
 				result.openapi31(true);
+                openAPI.setSpecVersion(SpecVersion.V31);
 			}
             if (!value.startsWith("3.0.") && !value.startsWith("3.1.")){
                 result.warning(location, "The provided definition does not specify a valid version field");
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 a7423022..e4f32505 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
@@ -5,6 +5,7 @@ import io.swagger.v3.oas.models.OpenAPI;
 import io.swagger.v3.oas.models.Operation;
 import io.swagger.v3.oas.models.PathItem;
 import io.swagger.v3.oas.models.Paths;
+import io.swagger.v3.oas.models.SpecVersion;
 import io.swagger.v3.oas.models.callbacks.Callback;
 import io.swagger.v3.oas.models.examples.Example;
 import io.swagger.v3.oas.models.headers.Header;
@@ -379,7 +380,15 @@ public class ResolverFully {
             boolean adjacent = (hasAllOf && hasAnyOf) || (hasAllOf && hasOneOf) || (hasAnyOf && hasOneOf);
 
             if (aggregateCombinators && (hasAllOf || adjacent)) {
-                Schema combinedModel = SchemaTypeUtil.createSchema(composedSchema.getType(), composedSchema.getFormat());
+                Schema combinedModel = null;
+                if (SpecVersion.V30.equals(composedSchema.getSpecVersion())) {
+                    combinedModel = SchemaTypeUtil.createSchema(getSchemaType(composedSchema), composedSchema.getFormat());
+                } else {
+                    combinedModel = new JsonSchema();
+                    combinedModel.setFormat(composedSchema.getFormat());
+                    combinedModel.setTypes(composedSchema.getTypes());
+                }
+
 //                combinedModel.setDefault(composedSchema.getDefault());
                 Set<Object> examples = new HashSet<>();
                 Set<Object> defaultValues = new HashSet<>();
@@ -436,8 +445,12 @@ public class ResolverFully {
                 Schema property = updated.get(key);
 
                 if (property.getProperties() != model.getProperties()) {
-                    if (property.getType() == null) {
-                        property.setType("object");
+                    if (!hasSchemaType(property)) {
+                        if (SpecVersion.V30.equals(property.getSpecVersion())) {
+                            property.setType("object");
+                        } else {
+                            property.addType("object");
+                        }
                     }
                     model.addProperties(key, property);
                 } else {
@@ -453,6 +466,22 @@ public class ResolverFully {
         return result;
     }
 
+    protected String getSchemaType(Schema schema) {
+        if (SpecVersion.V30.equals(schema.getSpecVersion())) {
+            return schema.getType();
+        }
+        if (schema.getTypes() != null && schema.getTypes().size() == 1) {
+            return (String)schema.getTypes().iterator().next();
+        }
+        return null;
+    }
+
+    protected boolean hasSchemaType(Schema schema) {
+        if (SpecVersion.V30.equals(schema.getSpecVersion())) {
+            return schema.getType() != null;
+        }
+        return schema.getTypes() != null && schema.getTypes().size() > 0;
+    }
     public Map<String,Example> resolveExample(Map<String,Example> examples){
 
         Map<String,Example> resolveExamples = examples;
diff --git a/pom.xml b/pom.xml
index 0113ebb2..ef7cd522 100644
--- a/pom.xml
+++ b/pom.xml
@@ -406,7 +406,7 @@
         <swagger-parser-v2-version>1.0.63</swagger-parser-v2-version>
         <commons-io-version>2.11.0</commons-io-version>
         <slf4j-version>1.7.30</slf4j-version>
-        <swagger-core-version>2.2.4</swagger-core-version>
+        <swagger-core-version>2.2.6</swagger-core-version>
         <swagger-core-v2-version>1.6.8</swagger-core-v2-version>
         <junit-version>4.13.2</junit-version>
         <testng-version>6.14.2</testng-version>


Test patch:
diff --git a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OAI31DeserializationTest.java b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OAI31DeserializationTest.java
index f4829123..22c33482 100644
--- a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OAI31DeserializationTest.java
+++ b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OAI31DeserializationTest.java
@@ -947,4 +947,44 @@ public class OAI31DeserializationTest {
         assertNull(profile.getProperties());
 
     }
+
+    @Test(description = "Test Issue 1801")
+    public void test31Issue1801() {
+        ParseOptions options = new ParseOptions();
+        SwaggerParseResult result = new OpenAPIV3Parser().readLocation( "3.1.0/issue-1801.yaml", null, options);
+        assertNotNull(result.getOpenAPI());
+        OpenAPI openAPI = result.getOpenAPI();
+        Schema firstAllOf = (Schema)openAPI.getComponents().getSchemas().get("AllofWithTheLastEmptySchema").getAllOf().get(0);
+        assertEquals(firstAllOf.getTypes().iterator().next(), "number");
+        assertEquals(firstAllOf.getType(), null);
+        Schema secondAllOf = (Schema)openAPI.getComponents().getSchemas().get("AllofWithTheLastEmptySchema").getAllOf().get(1);
+        assertEquals(secondAllOf.getTypes(), null);
+        assertEquals(firstAllOf.getType(), null);
+
+        try {
+            System.setProperty("bind-type", "true");
+            result = new OpenAPIV3Parser().readLocation("3.1.0/issue-1801.yaml", null, options);
+            assertNotNull(result.getOpenAPI());
+            openAPI = result.getOpenAPI();
+            firstAllOf = (Schema) openAPI.getComponents().getSchemas().get("AllofWithTheLastEmptySchema").getAllOf().get(0);
+            assertEquals(firstAllOf.getTypes().iterator().next(), "number");
+            assertEquals(firstAllOf.getType(), "number");
+            secondAllOf = (Schema) openAPI.getComponents().getSchemas().get("AllofWithTheLastEmptySchema").getAllOf().get(1);
+            assertEquals(secondAllOf.getTypes(), null);
+            assertEquals(secondAllOf.getType(), null);
+        } finally {
+            System.setProperty("bind-type", "false");
+        }
+    }
+
+    @Test(description = "Test Issue 1821")
+    public void test31Issue1821() {
+        ParseOptions options = new ParseOptions();
+        options.setResolve(true);
+        options.setResolveFully(true);
+        SwaggerParseResult result = new OpenAPIV3Parser().readLocation( "3.1.0/issue-1821.yaml", null, options);
+        assertNotNull(result.getOpenAPI());
+        Schema id = (Schema)result.getOpenAPI().getComponents().getSchemas().get("Rule").getProperties().get("id");
+        assertEquals(id.getTypes().iterator().next(), "string");
+    }
 }
diff --git a/modules/swagger-parser-v3/src/test/resources/3.1.0/issue-1801.yaml b/modules/swagger-parser-v3/src/test/resources/3.1.0/issue-1801.yaml
new file mode 100644
index 00000000..55e2287d
--- /dev/null
+++ b/modules/swagger-parser-v3/src/test/resources/3.1.0/issue-1801.yaml
@@ -0,0 +1,17 @@
+openapi: 3.1.0
+servers:
+  - url: https://someserver.com/v1
+info:
+  title: openapi 3.1.0 sample spec
+  version: 0.0.1
+  description: sample spec for testing openapi functionality, built from json schema
+    tests for draft2020-12
+tags: []
+paths: {}
+components:
+  schemas:
+    AllofWithTheLastEmptySchema:
+      $schema: https://json-schema.org/draft/2020-12/schema
+      allOf:
+        - type: number
+        - {}
diff --git a/modules/swagger-parser-v3/src/test/resources/3.1.0/issue-1821.yaml b/modules/swagger-parser-v3/src/test/resources/3.1.0/issue-1821.yaml
new file mode 100644
index 00000000..a098ac35
--- /dev/null
+++ b/modules/swagger-parser-v3/src/test/resources/3.1.0/issue-1821.yaml
@@ -0,0 +1,22 @@
+openapi: 3.1.0
+paths: {}
+components:
+  schemas:
+    Rule:
+      type: object
+      properties:
+        id:
+          type: string
+          format: uuid
+        name:
+          type: string
+        condition:
+          type: string
+        order:
+          type: integer
+        enabled:
+          type: boolean
+        version:
+          type: integer
+          description: Version counter
+    
\ No newline at end of file