OpenAPITools / OpenAPITools/openapi-generator

[BUG][JAVA] OneOf and inline creates a selfreference in case of naming matching

Open
#20,095 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Issue: Bug
Dominant language
Java
Stars
26.8k
Forks
7.7k
PR merge metrics
PR metrics pending

Description

Bug Report Checklist
  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator (example)?
  • Have you tested with the latest master to confirm the issue still exists?
  • Have you searched for related issues/PRs?
  • What's the actual output vs expected output?
  • [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description

If I have a a component that references another component in a oneOf the naming of the classes becomes the same and it creates an object with a reference to itself, with other words when generating the classes one of them gets replaced by the other one.

We are not the owners of the schema and can modify it locally, but it is a big file and a lot to modify everytime we get a new version of the definition.

For now we are using manually adding modelNameMapping to handle this, but would prefer if the naming would make sure it does not replace another already defined class.

Expected is that 2 classes that get generated, one for the oneof and one for the actual component.
Actual is that only the oneof is generated.

openapi-generator version

7.9.0

OpenAPI declaration file content or url

A simplified json verified in https://editor.swagger.io/ from the 12k line json we use:

{
  "openapi": "3.0.0",
  "info": {
    "title": "API title",
    "version": "1.0.0"
  },
  "paths": {
    "/api/test": {
      "get": {
        "operationId": "Test",
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Margin"
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
	  "Margin": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "price": {
            "nullable": true,
            "oneOf": [
              {
                "$ref": "#/components/schemas/MarginPrice"
              }
            ]
          },
          "percent": {
            "nullable": true,
            "oneOf": [
              {
                "$ref": "#/components/schemas/Percent"
              }
            ]
          }
        }
      },
      "MarginPrice": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "value": {
            "type": "number",
            "format": "decimal",
            "nullable": true
          },
          "currency": {
            "nullable": true,
            "oneOf": [
              {
                "$ref": "#/components/schemas/Currency"
              }
            ]
          }
        }
      },
	  "Percent": {
		"type": "object",
		"additionalProperties": false,
		"properties": {
		  "value": {
			"type": "number",
			"format": "decimal",
			"nullable": true
		  }
		}
	  },
	  "Currency": {
		"type": "object",
		"description": "Currency identifier.",
		"additionalProperties": false,
		"required": [
		  "code"
		],
		"properties": {
		  "code": {
			"type": "string",
			"description": "Three-letter code identifying the currency according to ISO 4217, e.g. \"SEK\", \"EUR\".",
			"maxLength": 3,
			"minLength": 3,
			"pattern": "AUD|CAD|CHF|CNY|CZK|DKK|EUR|GBP|HKD|HUF|IDR|ILS|ISK|JPY|KWD|MAD|MXN|MYR|NOK|NZD|PLN|RUB|SAR|SEK|SGD|THB|TRY|USD|ZAR",
			"nullable": false
		  }
		}
	  }
    }
  }
}
Related issues/PRs

https://github.com/OpenAPITools/openapi-generator/issues/18039

Suggest a fix

In org.openapitools.codegen.InlineModelResolver.gatherInlineModels it has a code that looks like the following:
String schemaName = resolveModelName(prop.getTitle(), modelPrefix + "_" + propName);
Resulting in a schemaName that is parentName_propName.
In org.openapitools.codegen.AbstractJavaCodegen.toModelName it has the following code:

        // phone_number => PhoneNumber
        final String camelizedName = camelize(nameWithPrefixSuffix);

that is used to define the classname for the class. Resulting in a classname of parentNamePropName

With this example above we would get two schemas MarginPrice and Margin_price. When converting them to classes both will be named MarginPrice and it results in the oneOf-class being the winner and the original MarginPrice gets replaced.

The suggested fix would be to have similar to what uniqueName does for InlineModelResolver, but on classname level.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with org.openapitools.codegen.InlineModelResolver.gatherInlineModels and the schemaName construction described in the issue, then trace how org.openapitools.codegen.AbstractJavaCodegen.toModelName camelizes both names. Reproduce the supplied OpenAPI schema with the Java generator and verify that both the oneOf model and the referenced MarginPrice model are generated without one replacing the other.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
backend-api-design, devtools
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.