OpenAPITools / openapi-generator

OpenAPI Generator allows generation of API client libraries (SDK generation), server stubs, documentation and configuration automatically given an OpenAPI Spec (v2, v3)
https://openapi-generator.tech
Apache License 2.0
21.86k stars 6.59k forks source link

[BUG][JAVA] AllOf with mapping generates wrong JsonSubTypes annotations #14917

Closed leonard84 closed 1 year ago

leonard84 commented 1 year ago

Bug Report Checklist

Description

The generator adds subtypes where they don't belong and doesn't respect the mapping.

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "petType", visible = true)
@JsonSubTypes({
  @JsonSubTypes.Type(value = Cat.class, name = "Cat"),        // <--- should not be generated
  @JsonSubTypes.Type(value = Dog.class, name = "Dog"),        // <--- should not be generated
  @JsonSubTypes.Type(value = Lizard.class, name = "Lizard"),  // <--- should not be generated
  @JsonSubTypes.Type(value = Cat.class, name = "cat"),
  @JsonSubTypes.Type(value = Dog.class, name = "dog"),
  @JsonSubTypes.Type(value = Lizard.class, name = "lizard"),
})

public class Pet
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "petType", visible = true)
// vvvvvv This should not be generated at all vvvv
@JsonSubTypes({
  @JsonSubTypes.Type(value = Cat.class, name = "cat"),
  @JsonSubTypes.Type(value = Dog.class, name = "dog"),
  @JsonSubTypes.Type(value = Lizard.class, name = "lizard"),
})

public class Cat extends Pet {

similarly the static mapper is wrong:

Pet:

static {
  // Initialize and register the discriminator mappings.
  Map<String, Class<?>> mappings = new HashMap<String, Class<?>>();
  mappings.put("Cat", Cat.class);
  mappings.put("Dog", Dog.class);
  mappings.put("Lizard", Lizard.class);
  mappings.put("cat", Cat.class);
  mappings.put("dog", Dog.class);
  mappings.put("lizard", Lizard.class);
  mappings.put("Pet", Pet.class);
  JSON.registerDiscriminator(Pet.class, "petType", mappings);
}

Cat:

static {
  // Initialize and register the discriminator mappings.
  Map<String, Class<?>> mappings = new HashMap<String, Class<?>>();
  mappings.put("cat", Cat.class);
  mappings.put("dog", Dog.class);
  mappings.put("lizard", Lizard.class);
  mappings.put("Cat", Cat.class);
  JSON.registerDiscriminator(Cat.class, "petType", mappings);
}

This causes broken serialization as can be seen here https://github.com/gradle/gradle-enterprise-api-samples/blob/de89e6b8d702d1e08df1f09fea419e1c5e87d543/src/test/java/Test.java#L36-L40

openapi-generator version

6.4.0

OpenAPI declaration file content or url
openapi: 3.0.0
info:
  title: test
  description: >-
    test schema
  version: 1.0.0
servers:
  - url: 'http://test.com'
    description: stage
paths:
  /demo:
    get:
      summary: placeholder summary
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Pet'
components:
  schemas:
    AllPets:
      type: object
      properties:
        pets:
          type: array
          items:
            $ref: '#/components/schemas/Pet'
    Pet:
      type: object
      required:
        - petType
      properties:
        petType:
          type: string
      discriminator:
        propertyName: petType
        mapping:
          cat: '#/components/schemas/Cat'
          dog: '#/components/schemas/Dog'
          lizard: '#/components/schemas/Lizard'
    Cat:
      allOf:
        - $ref: '#/components/schemas/Pet'
        - type: object
          # all other properties specific to a `Cat`
          properties:
            name:
              type: string
    Dog:
      allOf:
        - $ref: '#/components/schemas/Pet'
        - type: object
          # all other properties specific to a `Dog`
          properties:
            bark:
              type: string
    Lizard:
      allOf:
        - $ref: '#/components/schemas/Pet'
        - type: object
          # all other properties specific to a `Lizard`
          properties:
            lovesRocks:
              type: boolean
Generation Details

https://github.com/gradle/gradle-enterprise-api-samples/blob/de89e6b8d702d1e08df1f09fea419e1c5e87d543/build.gradle.kts#L36-L58

Steps to reproduce

Checkout https://github.com/gradle/gradle-enterprise-api-samples/tree/openapi-generator-issue_allOf_Subtypes Run ./gradlew :test

Related issues/PRs
Suggest a fix

Remove the typeinfo on subclasses and filter out the duplicate type info for mappings.

WojciechZankowski commented 1 year ago

@leonard84 I believe it might be already reported

https://github.com/OpenAPITools/openapi-generator/issues/13150 https://github.com/OpenAPITools/openapi-generator/issues/13682

and opened PR: https://github.com/OpenAPITools/openapi-generator/pull/13815