Skip to content

[BUG][JAVA] Problem with request serialization / deserialization in case of oneOf caused by PR #20939 #22896

@GooDer

Description

@GooDer

This problem is related to change in #20939 related to bug report #20938.

So it worked in version 7.14 and it is not working since actual 7.19.

I agree that correct behavior should be that only mapped discriminator should be included in generated interface for parent type, but it now breaks serialization / deserialization in client vs server communication.

Since parent interface contains these annotations it will override property of discriminator via Jackson mapper to simple class name but server now expect to receive explicit mapping that we have in yaml definition.

I will borrow example from original bug report with slight alternation:

    FruitRequest:
      discriminator:
        mapping:
          APPLE: '#/components/schemas/AppleRequest'
          BANANA: '#/components/schemas/BananaRequest'
        propertyName: fruitType
      oneOf:
      - $ref: '#/components/schemas/AppleRequest'
      - $ref: '#/components/schemas/BananaRequest'
      properties:
        fruitType:
          $ref: '#/components/schemas/FruitType'
      required:
      - fruitType
      type: object
      x-one-of-name: Fruit
    AppleRequest:
      properties:
        seeds:
          type: integer
      required:
      - seeds
      type: object
    BananaRequest:
      properties:
        length:
          type: integer
      required:
      - length
      type: object

then we will have:

@JsonIgnoreProperties(
    value = {"fruitType"},
    allowSetters = true
)
@JsonTypeInfo(
    use = Id.NAME,
    include = As.PROPERTY,
    property = "fruitType",
    visible = true
)
@JsonSubTypes({
  @JsonSubTypes.Type(value = Apple.class, name = "APPLE"),
  @JsonSubTypes.Type(value = Banana.class, name = "BANANA"),
  @JsonSubTypes.Type(value = Apple.class, name = "AppleRequest"),    // <-- not any more
  @JsonSubTypes.Type(value = Banana.class, name = "BananaRequest")   // <-- not any more
})

@Generated(value = "org.openapitools.codegen.languages.SpringCodegen", comments = "Generator version: 7.13.0-SNAPSHOT")
public interface Fruit {

Since fruitType is marked as ignored it will not be passed from client's DTO to the request and simpleClassName will be used which will not match on server side.
If we remove that JsonIgnoreProperties then both, the explicit discriminator property value and simpleClassName will be sent to server as fruitType and again, fail on deserialization.

Only think that worked for me was to also specify

@JsonTypeInfo(
use = Id.NAME,
include = As.EXISTING_PROPERTY,
property = "fruitType",
visible = true
)

that results in:

// no more @JsonIgnoreProperties
@JsonTypeInfo(
    use = Id.NAME,
    include = As.EXISTING_PROPERTY,
    property = "fruitType",
    visible = true
)
@JsonSubTypes({
  @JsonSubTypes.Type(value = Apple.class, name = "APPLE"),
  @JsonSubTypes.Type(value = Banana.class, name = "BANANA"),
})

@Generated(value = "org.openapitools.codegen.languages.SpringCodegen", comments = "Generator version: 7.13.0-SNAPSHOT")
public interface Fruit {

then its working correctly with only explicit discriminator mapping in parent interface.

There is also workaround for this issue, to define inside openapi.yml also mapping for simpleClassName

e.g.

    FruitRequest:
      discriminator:
        mapping:
          APPLE: '#/components/schemas/AppleRequest'
          BANANA: '#/components/schemas/BananaRequest'
          AppleRequest: '#/components/schemas/AppleRequest'
          BananaRequest: '#/components/schemas/BananaRequest'

I don't kwow if possible change in https://github.com/OpenAPITools/openapi-generator/blob/master/modules/openapi-generator/src/main/resources/JavaSpring/typeInfoAnnotation.mustache would break anything else, but at least some options to enable old behavior would be greatly appreciated :-)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions