Repository: swagger-api/swagger-parser
Pull request #735 (2018-06-07 23:29:58)

Extensions in Paths and Responses were not being parsed
solves issue #719 in oas3


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 3bdeb8f1..f2479680 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
@@ -467,7 +467,10 @@ public class OpenAPIDeserializer {
         for (String pathName : pathKeys) {
             JsonNode pathValue = obj.get(pathName);
             if(pathName.startsWith("x-")) {
-                result.unsupported(location, pathName, pathValue);
+                Map <String,Object> extensions = getExtensions(obj);
+                if(extensions != null && extensions.size() > 0) {
+                    paths.setExtensions(extensions);
+                }
             } else {
                 if (!pathValue.getNodeType().equals(JsonNodeType.OBJECT)) {
                     result.invalidType(location, pathName, "object", pathValue);
@@ -2234,11 +2237,18 @@ public class OpenAPIDeserializer {
         Set<String> keys = getKeys(node);
 
         for (String key : keys) {
-            ObjectNode obj = getObject(key, node, false, String.format("%s.%s", location, "responses"), result);
-            if(obj != null) {
-                ApiResponse response = getResponse(obj, String.format("%s.%s", location, key), result);
-                if(response != null) {
-                    apiResponses.put(key, response);
+            if (key.startsWith("x-")) {
+                Map <String,Object> extensions = getExtensions(node);
+                if(extensions != null && extensions.size() > 0) {
+                    apiResponses.setExtensions(extensions);
+                }
+            } else {
+                ObjectNode obj = getObject(key, node, false, String.format("%s.%s", location, "responses"), result);
+                if (obj != null) {
+                    ApiResponse response = getResponse(obj, String.format("%s.%s", location, key), result);
+                    if (response != null) {
+                        apiResponses.put(key, response);
+                    }
                 }
             }
         }


Test patch:
diff --git a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIV3ParserTest.java b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIV3ParserTest.java
index 13dd389e..94da9ced 100644
--- a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIV3ParserTest.java
+++ b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIV3ParserTest.java
@@ -56,6 +56,17 @@ public class OpenAPIV3ParserTest {
     protected int serverPort = getDynamicPort();
     protected WireMockServer wireMockServer;
 
+    @Test
+    public void testIssue719() {
+        final OpenAPI openAPI = new OpenAPIV3Parser().readLocation("extensions-responses.yaml", null, new ParseOptions()).getOpenAPI();
+
+        Assert.assertNotNull(openAPI);
+
+        Assert.assertNotNull(openAPI.getPaths().getExtensions());
+        Assert.assertNotNull(openAPI.getPaths().get("/something").getGet().getResponses().getExtensions());
+
+    }
+
     @Test
     public void issue682() throws Exception {
         OpenAPIV3Parser parser = new OpenAPIV3Parser();
@@ -798,8 +809,7 @@ public class OpenAPIV3ParserTest {
 
         assertEquals(((Map) openAPI.getExtensions().get("x-some-vendor")).get("sometesting"), "bye!");
         assertEquals(openAPI.getPaths().get("/foo").getExtensions().get("x-something"), "yes, it is supported");
-        assertTrue(result.getMessages().size() == 1);
-        assertEquals(result.getMessages().get(0), "attribute paths.x-nothing is unsupported");
+       
     }
 
 
diff --git a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/util/OpenAPIDeserializerTest.java b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/util/OpenAPIDeserializerTest.java
index 8f5fe7b6..4f877d98 100644
--- a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/util/OpenAPIDeserializerTest.java
+++ b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/util/OpenAPIDeserializerTest.java
@@ -94,6 +94,7 @@ public class OpenAPIDeserializerTest {
         assertNotNull(openAPI.getComponents().getSchemas().get("mydefinition"));
 
 
+
     }
 
 
diff --git a/modules/swagger-parser-v3/src/test/resources/extensions-responses.yaml b/modules/swagger-parser-v3/src/test/resources/extensions-responses.yaml
new file mode 100644
index 00000000..ee8cb5c2
--- /dev/null
+++ b/modules/swagger-parser-v3/src/test/resources/extensions-responses.yaml
@@ -0,0 +1,155 @@
+openapi: 3.0.0
+servers: []
+info:
+  version: '1.0'
+  title: Extensions everywhere!
+  x-apis-json:
+    image: >-
+      https://s3.amazonaws.com/kinlane-productions/api-evangelist/t-shirts/KL_InApiWeTrust-1000.png
+    humanURL: 'http://developer.apievangelist.com'
+    baseURL: 'http://api.apievangelist.com/definitions/Analysis'
+    tags:
+      - blog
+      - industry
+      - analysis
+      - new
+      - API
+      - Application Programming Interface
+    properties:
+      - type: X-signup
+        url: 'https://apievangelist.3scale.net/'
+      - type: X-blog
+        url: 'http://developer.apievangelist.com/blog/'
+      - type: X-apicommonsmanifest
+        url: >-
+          https://raw.githubusercontent.com/kinlane/analysis-api/master/api-commons-manifest.json
+  contact:
+    name: Developer
+    x-contact-extension: Support not available on weekends
+  license:
+    name: Apache 2.0
+    x-notes: hello
+externalDocs:
+  description: Learn more about this API
+  url: 'http://example.com/api-docs'
+  x-docs-extension: something something
+tags:
+  - name: pets
+    x-tag-extension: fooooo
+    externalDocs:
+      description: Learn more about pet operations
+      url: 'http://example.com/api-docs'
+      x-tag-docs-extension: Yeah
+x-definitions:
+  DayOfWeek:
+    type: integer
+    format: int32
+    minimum: 0
+    maximum: 6
+paths:
+  /post:
+    post:
+      responses:
+        '200':
+          description: OK
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: object
+              properties:
+                status:
+                  type: string
+              required:
+                - status
+          application/xml:
+            schema:
+              type: object
+              properties:
+                status:
+                  type: string
+              required:
+                - status
+        required: true
+  x-paths-extension: value
+  /something:
+    x-path-item-extension: true
+    get:
+      x-version: 1.1
+      parameters:
+        - in: query
+          name: ids
+          schema:
+            type: array
+            items:
+              type: integer
+              x-example: 2
+      externalDocs:
+        description: Learn more about this operation
+        url: 'http://example.com/api-docs'
+        x-operation-docs-extension: foo bar
+      responses:
+        '200':
+          description: OK
+          x-response-extension: OK?!
+          headers:
+            X-Rate-Limit:
+              x-example: 200
+              schema:
+                type: integer
+        x-responses-extension: hello
+security:
+  - BasicAuth: []
+  - APIKeyHeader: []
+    APIKeyQueryParam: []
+  - OAuth2Implicit:
+      - 'read:pets'
+      - 'write:pets'
+components:
+  securitySchemes:
+    BasicAuth:
+      type: http
+      description: Basic authentication using login and password
+      scheme: basic
+    APIKeyHeader:
+      type: apiKey
+      in: header
+      name: X-API-Key
+    APIKeyQueryParam:
+      type: apiKey
+      in: query
+      name: api_key
+    OAuth2Implicit:
+      type: oauth2
+      x-auth-extension: hello
+      flows:
+        implicit:
+          authorizationUrl: 'http://swagger.io/api/oauth/dialog'
+          scopes:
+            'write:pets': modify pets in your account
+            'read:pets': read your pets
+            x-scope-extension: hello
+  schemas:
+    String:
+      type: string
+      nullable: true
+    ArrayOfInt:
+      type: array
+      items:
+        type: integer
+        nullable: true
+      nullable: true
+    User:
+      type: object
+      xml:
+        name: USER
+        x-xml-extension: something
+    Dictionary:
+      type: object
+      additionalProperties:
+        type: integer
+        x-extension: Foo bar
+      externalDocs:
+        description: Learn more about dictionaries
+        url: 'http://api.example.com/docs'
+        x-extension: Yeah
\ No newline at end of file