Skip to content

Conversation

Copy link

Copilot AI commented Jan 30, 2026

  • Change visitedMap from HashMap to IdentityHashMap in OpenAPI31Traverser.java
  • Change visitedMap from HashMap to IdentityHashMap in IdsTraverser.java (if exists)
  • Add import statement for IdentityHashMap in both files
  • Create focused test that validates the fix
  • Run existing tests to ensure no regressions
  • Verify the fix solves the issue with identical inline objects
Original prompt

This section details on the original issue you should resolve

<issue_title>[Bug]: OpenAPI 3.1 Parser Unexpectedly Merges Identical Inline Objects When resolve=true</issue_title>
<issue_description>## Description

When parsing an OpenAPI 3.1 specification with ParseOptions.setResolve(true), the OpenAPIDereferencer31 unexpectedly merges identical inline objects (schemas, responses, etc.) into the same object reference. This behavior is inconsistent with the OpenAPI specification and causes issues for code generation tools.

Affected Version

2.1.37

Steps to Reproduce

Test OpenAPI 3.1 Spec (swagger.json):

{
  "openapi": "3.1.0",
  "info": {
    "title": "API",
    "version": "1.0"
  },
  "paths": {
    "/path1": {
      "post": {
        "responses": {
          "200": {
            "description": "result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": { "type": "string" },
                    "status": { "type": "string" }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/path2": {
      "post": {
        "responses": {
          "200": {
            "description": "result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": { "type": "string" },
                    "status": { "type": "string" }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

Test Code:

// With resolve=true
ParseOptions options1 = new ParseOptions();
options1.setResolve(true);
SwaggerParseResult result1 = new OpenAPIParser().readLocation("swagger.json", null, options1);

ApiResponse path1Response = result1.getOpenAPI().getPaths().get("/path1").getPost().getResponses().get("200");
ApiResponse path2Response = result1.getOpenAPI().getPaths().get("/path2").getPost().getResponses().get("200");

System.out.println(path1Response == path2Response);  // Prints: true (UNEXPECTED!)

// With resolve=false
ParseOptions options2 = new ParseOptions();
options2.setResolve(false);
SwaggerParseResult result2 = new OpenAPIParser().readLocation("swagger.json", null, options2);

ApiResponse path1Response2 = result2.getOpenAPI().getPaths().get("/path1").getPost().getResponses().get("200");
ApiResponse path2Response2 = result2.getOpenAPI().getPaths().get("/path2").getPost().getResponses().get("200");

System.out.println(path1Response2 == path2Response2);  // Prints: false (EXPECTED)

In OpenAPI31Traverser.java, the traversal logic uses:

if (visitedMap.containsKey(mediaType)) {
    return (MediaType)visitedMap.get(mediaType);  // Returns cached object
}

Since MediaType, Schema, ApiResponse, and other model classes override equals() to compare content rather than object identity, the visitedMap incorrectly identifies different inline objects as the same when their content matches.

Expected Behavior

According to the OpenAPI 3.1 specification, two inline objects with identical content should remain as separate, independent objects unless they are explicitly referenced using $ref. Each inline definition should maintain its own object identity.

Actual Behavior

When resolve=true is enabled, the OpenAPI31Traverser uses a visitedMap (HashMap) that relies on the equals() method to cache visited objects. When it encounters a second inline object with identical content, it returns the cached reference from the first object instead of treating them as separate entities.

Additional Context

This issue only affects OpenAPI 3.1 parsing with resolve=true. The older OpenAPI 3.0 resolver (OpenAPIResolver) does not exhibit this behavior. The issue was introduced with the new OpenAPIDereferencer31 implementation.

The DISABLE_OAS31_RESOLVE environment variable can be used as a workaround to disable OAS 3.1 resolution, but this prevents proper $ref resolution as well.

Checklist

  • I have searched the existing issues and this is not a duplicate.
  • I have provided sufficient information for maintainers to reproduce the issue.</issue_description>

Comments on the Issue (you are @copilot in this section)


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: OpenAPI 3.1 Parser Unexpectedly Merges Identical Inline Objects When resolve=true

2 participants