swagger-api / swagger-codegen

swagger-codegen contains a template-driven engine to generate documentation, API clients and server stubs in different languages by parsing your OpenAPI / Swagger definition.
http://swagger.io
Apache License 2.0
16.9k stars 6.03k forks source link

Polymorphism issue #12083

Open deblockt opened 1 year ago

deblockt commented 1 year ago
Description

When using polymorphism, the JsonSubType is duplicated, like on this example:

@JsonIgnoreProperties(
  value = "type", // ignore manually set type, it will be automatically generated by Jackson during serialization
  allowSetters = true // allows the type to be set during deserialization
)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type", visible = true)
@JsonSubTypes({
  @JsonSubTypes.Type(value = CurrencyContextValue.class, name = "CurrencyContextValue"),
  @JsonSubTypes.Type(value = DateTimeContextValue.class, name = "DateTimeContextValue"),
  @JsonSubTypes.Type(value = CurrencyContextValue.class, name = "currency"),
  @JsonSubTypes.Type(value = DateTimeContextValue.class, name = "date_time"),
})

In this example the JsonSubTypes.Type annotation is duplicated. If I remove the allOf on CurrencyContextValue and on DateTimeContextValue I have no issue. It seem that the allOf don't use the discriminator field. I can't find any solution.

Swagger-codegen version

I use the gradle plugin org.openapitools:openapi-generator-gradle-plugin:6.4.0

Swagger declaration file content or url
CurrencyContextValue:
      required:
        - currency
      type: object
      example:
        type: currency
        currency: EUR
      allOf:
        - $ref: '#/components/schemas/WhatsAppContextValue'
        - type: object
          properties:
            currency:
              type: string
    DateTimeContextValue:
      required:
        - dateTime
      type: object
      example:
        type: date_time
        dateTime: '2022-10-10T10:10:10.000'
      allOf:
        - $ref: '#/components/schemas/WhatsAppContextValue'
        - type: object
          properties:
            dateTime:
              type: string
              format: date-time
    WhatsAppContext:
      type: object
      properties:
        header:
          type: array
          items:
            oneOf:
              - $ref: '#/components/schemas/CurrencyContextValue'
              - $ref: '#/components/schemas/DateTimeContextValue'
            discriminator:
              propertyName: type
      description: The context is used to fill template variables.
    WhatsAppContextValue:
      required:
        - type
      type: object
      properties:
        type:
          type: string
      discriminator:
        propertyName: type
        mapping:
          currency: '#/components/schemas/CurrencyContextValue'
          date_time: '#/components/schemas/DateTimeContextValue'

This swagger is generated from java annotation using these class:

@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    property = "type"
)
@JsonSubTypes({
    @JsonSubTypes.Type(value = WhatsAppContextValue.TextContextValue.class, name = "text"),
    @JsonSubTypes.Type(value = WhatsAppContextValue.CurrencyContextValue.class, name = "currency"),
    @JsonSubTypes.Type(value = WhatsAppContextValue.DateTimeContextValue.class, name = "date_time")
})
@Schema(
    name = "WhatsAppContextValue",
    discriminatorProperty = "type",
    discriminatorMapping = {
        @DiscriminatorMapping(value = "text", schema = WhatsAppContextValue.TextContextValue.class),
        @DiscriminatorMapping(value = "currency", schema = WhatsAppContextValue.CurrencyContextValue.class),
        @DiscriminatorMapping(value = "date_time", schema = WhatsAppContextValue.DateTimeContextValue.class)
    }
)
public sealed interface WhatsAppContextValue 

Thanks for you help

axshani commented 1 year ago

I'm using polymorpishm like this:

Create ContextType and add to each of your contexts:

 "allOf": [
        {
          "$ref": "./context.json"
        },
        {
          "type": "object"
       ...
       }

And then inside Context add:

"discriminator": {
          "propertyName": "type",
          "mapping": {
                  "textContextValue": "#/definitions/TextContextValue",
                  "currencyContextValue": "#/definitions/CurrencyContextValue",
                  "whatsAppContextValue": "#/definitions/WhatsAppContextValue"
          }
        }