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
17.02k stars 6.03k forks source link

Regression: Swagger CodeGen generates duplicate fields in child DTOs #12409

Open andrewfg opened 5 months ago

andrewfg commented 5 months ago

Regression v2.3.1 to v2.4.41

Problem

Background

In OpenHAB one of its 450 odd third party integrations uses Swagger CodeGen to convert an API YAML file to respective Java API DTOs. We were using CodeGen v2.3.1 but we recently attempted to upgrade to CodeGen v2.4.41 -- but failed.

The API and the respective YAML have API fields name 'type' and CodeGen v2.3.1 creates them them in the DTO and applies the @SerializedName("type") annotation to them. When attemting to use CodeGen v2.4.41 we started seeing GSON exceptions that the DTO "declares multiple JSON fields named 'type'".

I am wondering what happened, and how to fix it?

See this https://github.com/openhab/openhab-addons/issues/16779 for more..

andrewfg commented 5 months ago

The issue occurs when a YAML DTO extends another DTO as follows where TadoModeTerminationCondition implements allOf the fields of OverlayTerminationCondition. CodeGen v2.3.1 generates Java code in which the child DTO does NOT include the same fields as the parent DTO (since they are already inherently in the parent). By contrast CodeGen v2.4.41 generates code where the child DTO has fields that DUPLICATE the same fields in the parent. Which is what causes the GSON JSON deserializer to fall over..

================ YAML Definition ================

OverlayTerminationCondition:
    type: object
    discriminator: type
    properties:
      type:
        $ref: "#/definitions/OverlayTerminationConditionType"
      projectedExpiry:
        description: |
          [ISO8601 datetime](https://en.wikipedia.org/wiki/ISO_8601). E.g. `2015-09-28T15:03:20Z` with second precision.
          Only relevant when receiving an overlay, ignored when overlay is sent to the server. Indicates the expected time of
          termination for this overlay, if no app user moves. `null` means that the overlay never expires (by itself, unless manully removed).
        type: string
        format: date-time
        readOnly: true
    required:
    - type

TadoModeTerminationCondition:
    description: The overlay terminates when the tado mode changes or when the setting (power, temperature, ...) of the underlying block schedule changes (or when removed manually).
    x-discriminator-value: TADO_MODE
    allOf:
    - $ref: "#/definitions/OverlayTerminationCondition"

================ Output of Swagger CodeGen v2.3.1 ================

public class OverlayTerminationCondition  {
  @SerializedName("type")
  private OverlayTerminationConditionType type = null;

  @SerializedName("projectedExpiry")
  private OffsetDateTime projectedExpiry = null;

  ... methods
}

public class TadoModeTerminationCondition extends OverlayTerminationCondition  {

  .. inherited methods all annotated with @Override
}

================ Output of Swagger CodeGen v2.4.41 ================

public class OverlayTerminationCondition  {
  @SerializedName("type")
  private OverlayTerminationConditionType type = null;

  @SerializedName("projectedExpiry")
  private OffsetDateTime projectedExpiry = null;

  ... methods
}

public class TadoModeTerminationCondition extends OverlayTerminationCondition  {
  @SerializedName("type")
  private OverlayTerminationConditionType type = null;

  @SerializedName("projectedExpiry")
  private OffsetDateTime projectedExpiry = null;

  .. inherited methods all annotated with @Override
}
andrewfg commented 5 months ago

^ From deep Googling one hypothesis is the issue may be related to supportsInheritance. => Does anyone have thought on this? And is so, how would I set a different value of that property for the Swagger Maven plugin in the OpenHAB pom.xml file?