Skip to content

Parameters with the same name but different locations are incorrectly returned when using JSON references ($ref) with openapi 3.0.x. #2102

Open
@AdrianVasiliu

Description

@AdrianVasiliu

Multiple parameters with the same name but different locations (for instance, in: query vs in: header) are wrongly handled by the parser if:

  • the parameters are described using JSON references ($ref).
  • and the OpenAPI file declares its version as v3.0.x ("openapi": "3.0.0" or "openapi": "3.0.3").

The issue does NOT occur when either not using $ref, or declaring "openapi": "3.1.0".

This looks like a bug because:

a) It violates the OpenAPI spec (both v3.0 and v3.1):

A unique parameter is defined by a combination of a name and location.

https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.0.md#parameter-object

This should be respected regardless of whether the parameter is defined with, or without $ref.

b) I don't see a mention of a change in this area between v3.0 and v3.1 (for instance here or here) which would justify the difference of behaviour.


How to reproduce (holds at least for swagger-parser 2.1.22 and 2.1.19):

package parsertest;

import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.parameters.Parameter;
import io.swagger.v3.parser.OpenAPIV3Parser;
import io.swagger.v3.parser.core.models.ParseOptions;

import java.io.IOException;
import java.util.List;

public class ParserTest {
    public static void main(String[] args) throws IOException {
        test("src/test/resources/parsertest/openapi-ok.json");
        test("src/test/resources/jparsertest/openapi-ko.json");
    }
    
    private static void test(String openapiFile) throws IOException {
        System.out.println("=== OpenAPI file:" + openapiFile);
        final ParseOptions options = new ParseOptions();
        options.setResolve(true);
        options.setResolveCombinators(true);
        options.setResolveFully(true);
        
        final OpenAPI openAPI = new OpenAPIV3Parser().read(openapiFile, null, options);
        
        final List<Parameter> parameters = openAPI.getPaths().get("/myoperation").getGet().getParameters();
        parameters.forEach(parameter -> {
            if (parameter != null) {
                System.out.println("Parameter name: " + parameter.getName() + " in: " + parameter.getIn());
            }
        });
    }
}

openapi-ko.json:

{
  "openapi": "3.0.0",
  "paths": {
    "/myoperation": {
      "get": {
        "parameters": [
          {"$ref": "#/components/parameters/schemaParam1"},
          {"$ref": "#/components/parameters/schemaParam2"}
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
  }}}}}}},
  "components": {
    "parameters": {
      "schemaParam1": {
        "name": "myParam",
        "in": "query",
        "schema": {
          "type": "string"
        }
      },
      "schemaParam2": {
        "name": "myParam",
        "in": "header",
        "schema": {
          "type": "string"
        }
   }}}
}

openapi-ok.json:

{
  "openapi": "3.0.0",
  "paths": {
    "/myoperation": {
      "get": {
        "parameters": [
          {
            "in": "query",
            "name": "myParam",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "myParam",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
  }}}}}}}
}

Output:

=== OpenAPI file:src/test/resources/parsertest/openapi-ok.json
Parameter name: myParam in: query
Parameter name: myParam in: header
=== OpenAPI file:src/test/resources/parsertest/openapi-ko.json
Parameter name: myParam in: query

That is, for the OpenAPI using $ref, only one of the two parameters is returned by getParameters().

For comparison, if modifying the OpenAPI files to declare "openapi": 3.1.0, both the header and query parameter are returned:

=== OpenAPI file:src/test/resources/parsertest/openapi-ok.json
Parameter name: myParam in: query
Parameter name: myParam in: header
=== OpenAPI file:src/test/resources/parsertest/openapi-ko.json
Parameter name: myParam in: query
Parameter name: myParam in: header

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions