Repository: swagger-api/swagger-parser
Pull request #212 (2016-03-11 18:01:26)

Fix, test for #204 "allOf deserialised incorrectly"
Please review/accept this pull request to fix Issue #204. The fix is required by swagger-codegen Issue [#2258](https://github.com/swagger-api/swagger-codegen/issues/2258), for which I shall shortly be raising a PR. Many thanks.


Patch:
diff --git a/modules/swagger-parser/src/main/java/io/swagger/parser/util/SwaggerDeserializer.java b/modules/swagger-parser/src/main/java/io/swagger/parser/util/SwaggerDeserializer.java
index 9ead3c7f..b429de82 100644
--- a/modules/swagger-parser/src/main/java/io/swagger/parser/util/SwaggerDeserializer.java
+++ b/modules/swagger-parser/src/main/java/io/swagger/parser/util/SwaggerDeserializer.java
@@ -816,22 +816,24 @@ public class SwaggerDeserializer {
                 }
 
                 List<Model> allComponents = model.getAllOf();
-                if (allComponents.size() >= 1) {
+                int size = allComponents.size();
+                if (size >= 1) {
+                    // Parent is the first composed component, by definition.
                     model.setParent(allComponents.get(0));
-                    if (allComponents.size() >= 2) {
-                        model.setChild(allComponents.get(allComponents.size() - 1));
+                    Model child = null;
+                    if (size >= 2) {
                         List<RefModel> interfaces = new ArrayList<RefModel>();
-                        int size = allComponents.size();
-                        for (Model m : allComponents.subList(1, size - 1)) {
+                        for (Model m : allComponents.subList(1, size/* - 1*/)) {
                             if (m instanceof RefModel) {
-                                RefModel ref = (RefModel) m;
-                                interfaces.add(ref);
+                                interfaces.add((RefModel) m);
+                            } else if (m instanceof ModelImpl) {
+                                // NOTE: since ComposedModel.child allows only one inline child schema, the last one 'wins'.
+                                child = m;
                             }
                         }
                         model.setInterfaces(interfaces);
-                    } else {
-                        model.setChild(new ModelImpl());
                     }
+                    model.setChild(child == null ? new ModelImpl() : child);
                 }
             }
             else {
diff --git a/pom.xml b/pom.xml
index 35c5cfcf..56c374e6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -229,7 +229,7 @@
     <properties>
         <commons-io-version>2.4</commons-io-version>
         <slf4j-version>1.6.3</slf4j-version>
-        <swagger-core-version>1.5.8-SNAPSHOT</swagger-core-version>
+        <swagger-core-version>1.5.7</swagger-core-version>
         <junit-version>4.8.1</junit-version>
         <testng-version>6.9.6</testng-version>
         <jmockit-version>1.19</jmockit-version>


Test patch:
diff --git a/modules/swagger-parser/src/test/java/io/swagger/parser/util/SwaggerDeserializerTest.java b/modules/swagger-parser/src/test/java/io/swagger/parser/util/SwaggerDeserializerTest.java
index 2c59f9ee..1afdfd27 100644
--- a/modules/swagger-parser/src/test/java/io/swagger/parser/util/SwaggerDeserializerTest.java
+++ b/modules/swagger-parser/src/test/java/io/swagger/parser/util/SwaggerDeserializerTest.java
@@ -826,10 +826,16 @@ public class SwaggerDeserializerTest {
         assertTrue(result.getMessages().size() == 1);
     }
 
+    @Test
     public void testIssue151() throws Exception {
         String json =
                 "{\n" +
                 "    \"swagger\": \"2.0\",\n" +
+                "    \"info\": {\n" +
+                "        \"version\": \"2.0.0\",\n" +
+                "        \"title\": \"Test Issue 151\",\n" +
+                "        \"description\": \"Tests that ComposedModel vendor extensions are deserialized correctly.\"\n" +
+                "    },\n" +
                 "    \"paths\": {\n" +
                 "        \"/\": {\n" +
                 "            \"get\": {\n" +
@@ -879,6 +885,7 @@ public class SwaggerDeserializerTest {
         SwaggerParser parser = new SwaggerParser();
 
         SwaggerDeserializationResult result = parser.readWithInfo(json);
+        assertTrue("Parser returned errors:", result.getMessages().isEmpty());
         Swagger swagger = result.getSwagger();
 
         Map<String, Model> definitions = swagger.getDefinitions();
@@ -888,4 +895,105 @@ public class SwaggerDeserializerTest {
         assertFalse(allOfModel.getVendorExtensions().isEmpty());
         assertEquals("some data", allOfModel.getVendorExtensions().get("x-vendor-ext"));
     }
+
+    @Test
+    public void testIssue204_allOf() throws Exception {
+        String json =
+                "{\n" +
+                "    \"swagger\": \"2.0\",\n" +
+                "    \"info\": {\n" +
+                "        \"version\": \"2.0.0\",\n" +
+                "        \"title\": \"Test allOf API\",\n" +
+                "        \"description\": \"Tests the allOf API for parent, interface and child models.\"\n" +
+                "    },\n" +
+                "    \"paths\": {\n" +
+                "        \"/\": {\n" +
+                "            \"get\": {\n" +
+                "                \"responses\": {\n" +
+                "                    \"200\": {\n" +
+                "                        \"description\": \"OK\"\n" +
+                "                    }\n" +
+                "                }\n" +
+                "            }\n" +
+                "        }\n" +
+                "    },\n" +
+                "    \"definitions\": {\n" +
+                "        \"Pet\": {\n" +
+                "            \"type\": \"object\",\n" +
+                "            \"required\": [\n" +
+                "                \"id\"\n" +
+                "            ],\n" +
+                "            \"properties\": {\n" +
+                "                \"id\": {\n" +
+                "                    \"type\": \"integer\",\n" +
+                "                    \"format\": \"int64\"\n" +
+                "                }\n" +
+                "            }\n" +
+                "        },\n" +
+                "        \"Furry\": {\n" +
+                "            \"type\": \"object\",\n" +
+                "            \"required\": [\n" +
+                "                \"coatColour\"\n" +
+                "            ],\n" +
+                "            \"properties\": {\n" +
+                "                \"coatColour\": {\n" +
+                "                    \"type\": \"string\"\n" +
+                "                }\n" +
+                "            }\n" +
+                "        },\n" +
+                "        \"Dog\": {\n" +
+                "            \"type\": \"object\",\n" +
+                "            \"allOf\": [\n" +
+                "                {\n" +
+                "                    \"$ref\": \"#/definitions/Pet\"\n" +
+                "                },\n" +
+                "                {\n" +
+                "                    \"$ref\": \"#/definitions/Furry\"\n" +
+                "                },\n" +
+                "                {\n" +
+                "                    \"required\": [\n" +
+                "                        \"name\"\n" +
+                "                    ],\n" +
+                "                    \"properties\": {\n" +
+                "                        \"name\": {\n" +
+                "                            \"type\": \"string\"\n" +
+                "                        }\n" +
+                "                    }\n" +
+                "                }\n" +
+                "            ]\n" +
+                "        }\n" +
+                "    }\n" +
+                "}";
+
+        SwaggerParser parser = new SwaggerParser();
+
+        SwaggerDeserializationResult result = parser.readWithInfo(json);
+        assertTrue("Parser returned errors:", result.getMessages().isEmpty());
+        Swagger swagger = result.getSwagger();
+        assertNotNull("Parser result does not contain a Swagger instance", swagger);
+
+        Map<String, Model> definitions = swagger.getDefinitions();
+        assertNotNull("Swagger instance does not contain any definitions", definitions);
+        assertEquals("Missing/extraneous definition;", 3, definitions.size());
+
+        Model pet = definitions.get("Pet");
+        Model furry = definitions.get("Furry");
+        Model dog = definitions.get("Dog");
+
+        assertNotNull("Pet model not found", pet);
+        assertNotNull("Furry model not found", furry);
+        assertNotNull("Dog model not found", dog);
+        assertTrue("Dog model is not composed", dog instanceof ComposedModel);
+        ComposedModel dogComposed = (ComposedModel) dog;
+        assertTrue("Dog does not have a parent", dogComposed.getParent() instanceof RefModel);
+        RefModel dogParentRef = (RefModel) dogComposed.getParent();
+        Model dogParent = definitions.get(dogParentRef.getSimpleRef());
+        assertEquals("Dog does not extend Pet", pet, dogParent);
+        assertNotNull("Dog does not implement any interfaces", dogComposed.getInterfaces());
+        assertEquals("Dog implements the wrong number of interfaces;", 1, dogComposed.getInterfaces().size());
+        RefModel dogInterfaceRef = dogComposed.getInterfaces().get(0);
+        Model dogInterface = definitions.get(dogInterfaceRef.getSimpleRef());
+        assertEquals("Dog does not implement Furry;", furry, dogInterface);
+        assertTrue("Dog does not have child properties", dogComposed.getChild() instanceof ModelImpl);
+    }
 }