Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] [Java] schema with oneOfs will generated model-code where first entry will match all others #16710

Closed
5 of 6 tasks
skwakman opened this issue Oct 3, 2023 · 3 comments · Fixed by #16992
Closed
5 of 6 tasks

Comments

@skwakman
Copy link

skwakman commented Oct 3, 2023

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

Given an OpenAPI schema containing a component with several oneOf's, in which each oneOf entry has a unique 'type' value. Here's a partial example:

{
  "components": {
    "schemas": {
      "ResponseContent": {
        "discriminator": {
          "propertyName": "type"
        },
        "oneOf": [
          {
            "$ref": "#/components/schemas/Title"
          },
          {
            "$ref": "#/components/schemas/Subtitle"
          },
          {
            "$ref": "#/components/schemas/Paragraph"
          }
        ]
      },
      "Title": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "title"
            ]
          }
        }
      },
      "Subtitle": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "subtitle"
            ]
          }
        }
      },
      "Paragraph": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "paragraph"
            ]
          }
        }
      }
    }
  }
}

Using the 7.0.1 java generator, the above schema will generate this Title model:

public class Title {
  public enum TypeEnum {
    TITLE("title"),
    
    SUBTITLE("subtitle"),
    
    PARAGRAPH("paragraph");

// ...
public static TypeEnum fromValue(String value) {
      for (TypeEnum b : TypeEnum.values()) {
        if (b.value.equals(value)) {
          return b;
        }
      }
      throw new IllegalArgumentException("Unexpected value '" + value + "'");
    }
}

This indicates that the 7.0.1 java generator generates model code in which the first entry in the oneOf will match all the other entries. In the above case, the generated Title class matches with the typeEnum of title, subtitle and paragraph. This will cause the model to never be able to deserialize properly, as there are multiple options to deserialize json with type: 'subtitle' (because both Title and Subtitle classes match will it).

This did work properly in openapi-generator 6.6.0.

openapi-generator version

Issue observed in 7.0.1. It worked properly in 6.6.0.

OpenAPI declaration file content or url

See https://github.com/skwakman/openapi-generator-java-issue/blob/main/src/main/resources/example-schema.json .

Generation Details

See https://github.com/skwakman/openapi-generator-java-issue/blob/main/build.gradle.kts

Steps to reproduce

I've made an example project illustrating the issue.

  1. Check out https://github.com/skwakman/openapi-generator-java-issue
  2. run ./gradlew openApiGenerate
  3. See the generated code for Title in build/generate-resources/main/src/main/java/com/example/api/model/Title.java. Its 'TypeEnum' matches with all the type values of the other components. The code for the other components (for instance in build/generate-resources/main/src/main/java/com/example/api/model/Subtitle.java) show that they only match for their specific type value.
  4. Run the project's Main class in src/main/java to see what problem this causes: Jackson is not able to deserialize a Subtitle, because both Title and Subtitle classes match.

Change the version of openapi-generator in build.gradle.kts to 6.6.0, run ./gradlew clean and run steps 2-4 again. The Title class will contain the correct TypeEnum values.

Suggest a fix

There's probably a bug somewhere in the java generator, introduced since 7.0.1.

@wing328
Copy link
Member

wing328 commented Oct 5, 2023

There's probably a bug somewhere in the java generator, introduced since 7.0.1.

I wonder if you can do a git bisect to identify the commit causing the issue.

@skwakman
Copy link
Author

skwakman commented Oct 5, 2023

@wing328 this bug was introduced in this commit: 1561c33 .
The issue seems to be originating from the mergeProperties method introduced in this commit. I'm not entirely sure what's going on.. maybe the problem is that this new method is applied to all oneOf situations, where it should only apply to oneOf's inside included.array.items?

@wing328
Copy link
Member

wing328 commented Nov 5, 2023

cc @l3ender author of 1561c33

@martin-mfg just filed a fix. I'll test and merge later this coming week. Thanks @martin-mfg for the PR.

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

Successfully merging a pull request may close this issue.

2 participants