swagger-parser icon indicating copy to clipboard operation
swagger-parser copied to clipboard

External Refs with same name are ignored

Open anthochristen opened this issue 1 year ago • 1 comments

When external referenced components have the same name but different definitions, only the first is considered, the rest seem to be ignored. This seems to be because of the way the JSON pointers are used to derive the component name in Refutils.

RefUtils.java

   if (definitionPath != null) { //the name will come from the last element of the definition path

"the name will come from the last element of the definition path" - I couldn't find any documentation as to why this is done, nor did I see any mention of this in this spec. This could likely cause issues as the definitions with same names are allow if the it is provided in-line.

P.S: Originally identified by @crankydillo.

openapi.json

{
    "openapi": "3.0.3",
    "info": {
        "version": "1.0.0",
        "title": "OpenAPI Service",
        "description": "Sample OpenAPI generated swagger contract"
    },
    "paths": {
        "/a-path": {
            "post": {
                "operationId": "ignoredRefPost",
                "parameters": [
                    { "$ref": "./external_ref_1.json#/limit" }
                ],
                "requestBody": { "$ref": "external_ref_1.json#/a-request" },
                "responses": {
                    "200": {
                        "$ref": "external_ref_1.json#/a-response"
                    },
                    "default": {
                        "$ref": "#/components/responses/default-string"
                    }
                }
            },
            "put": {
                "operationId": "ignoredRefPut",
                "parameters": [
                    { "$ref": "./external_ref_2.json#/limit" }
                ],
                "requestBody": { "$ref": "external_ref_2.json#/a-request" },
                "responses": {
                    "200": {
                        "$ref": "external_ref_2.json#/a-response"
                    },
                    "default": {
                        "$ref": "#/components/responses/default-string"
                    }
                }
            }
        }
    },
    "components": {
        "responses": {
            "default-string": {
                "description": "some string",
                "content": {
                    "text/plain": {
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        }
    }
}

external_ref1.json

{
  "limit": {
    "name": "limit",
    "description": "There can be only 1!",
    "in": "query",
    "schema": {
      "type": "integer",
      "maximum": 1,
      "minimum": 0
    }
  },
 "a-request": {
   "required": true,
   "description": "a string req",
   "content": {
     "text/plain": {
       "schema": {
         "type": "string"
       }
     }
   }
},
  "a-response": {
    "description": "some string response",
    "content": {
      "text/plain": {
        "schema": {
          "type": "string"
        }
      }
    }
  }
}

external_ref_2.json

{
  "limit": {
    "name": "limit",
    "description": "There can be only 2!",
    "in": "query",
    "schema": {
      "type": "integer",
      "maximum": 2,
      "minimum": 0
    }
  },
  "a-response": {
    "description": "some string response",
    "content": {
      "appilication/json": {
        "schema": {
          "schema": {
            "$ref": "#/an-object"
            }
        }
      }
    }
  },
  "an-object": {
    "type": "object",
    "properties": {
      "a-prop": {
        "type": "string"
      }
    }
  },
  "a-request": {
    "required": true,
    "description": "a JSON req",
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/an-object"
        }
      }
    }
  }
}

Main.java

ParseOptions options = new ParseOptions();
options.setResolve(true);
OpenAPI openAPI = new OpenAPIV3Parser().read("openapi.json", null, options);
System.out.println("Parameters: " + openAPI.getComponents().getParameters().keySet());
System.out.println("Responses: " + openAPI.getComponents().getResponses().keySet());
System.out.println("Requests: " + openAPI.getComponents().getRequestBodies().keySet());

anthochristen avatar Feb 09 '24 12:02 anthochristen

Same here. Is this an expected behavior?

kota65535 avatar Feb 21 '24 19:02 kota65535