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] nullable oneOf deserialization incorrect for isNullable #20399

Open
5 tasks done
taviLaies opened this issue Jan 3, 2025 · 0 comments
Open
5 tasks done

Comments

@taviLaies
Copy link

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

When using a nullable oneOf property, deserialization does not preserve the isNullable flag.

openapi-generator version

All versions since 7.5.0.
7.4.0 works correctly.

OpenAPI declaration file content or url
openapi: 3.0.3
info:
  title: API
  description: Hello
  version: v1
servers:
  - url: http://localhost:8080/
    description: server url
tags:
  - name: "Hello"
    description: "The Hello resource"
paths:
  /hello:
    post:
      tags:
        - Hello
        - FIDO
      operationId: hello
      summary: Returns a hello message.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/HelloRequest'
      responses:
        '200': # status code
          description: Succeeded
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HelloResponse'

components:
  schemas:
    HelloRequest:
      type: object
      properties:
        message:
          type: string
          minLength: 1
          example: "friends"
        optionalField:
          type: integer
          nullable: true
        polymorphicProperties:
          type: array
          items:
            $ref: '#/components/schemas/ParentProperty'
        propertyOption:
          $ref: '#/components/schemas/PropertyOption'
      required:
      - message

    HelloResponse:
      type: object
      properties:
        message:
          type: string
          example: "Hello friends"

    ParentProperty:
      type: object
      discriminator:
        propertyName: "propertyType"
      properties:
        parentValue:
          type: string

    ChildProperty1:
      allOf:
        - $ref: '#/components/schemas/ParentProperty'
        - type: object
          properties:
            stringValue:
              type: string
            propertyType:
              type: string
              default: "ChildProperty1"
          required:
            - stringValue

    ChildProperty2:
      type: object
      allOf:
        - $ref: '#/components/schemas/ParentProperty'
        - type: object
          properties:
            intValue:
              type: integer
            propertyType:
              type: string
              default: "ChildProperty2"
          required:
            - intValue

    PropertyOption:
      nullable: true
      oneOf:
        - $ref: '#/components/schemas/PropertyOption1'
        - $ref: '#/components/schemas/PropertyOption2'

    PropertyOption1:
      type: object
      properties:
        stringValue:
          type: string
      required:
        - stringValue

    PropertyOption2:
      type: object
      properties:
        intValue:
          type: integer
      required:
        - intValue
Generation Details

I'm Using gradle plugin:

openApiGenerate {
    generatorName = 'java'
    additionalProperties = [
            sourceFolder : "",
            "annotationLibrary": "none",
            "library" : "jersey2",
            "performBeanValidation" : "true",
            "useBeanValidation" : "true",
            "useRuntimeException" : "true",
            "hideGenerationTimestamp" : "true",
            "useJakartaEe": "true"
    ]
}
Steps to reproduce

Generate Java models and perform a JSON round-trip of the DTO:

@Test
void request() throws JsonProcessingException {
    HelloRequest initial = new HelloRequest()
        .message("message")
        .optionalField(15)
        .polymorphicProperties(List.of(
                new ChildProperty1()
                        .stringValue("stringValue"),
                new ChildProperty2()
                        .intValue(10)))
        .propertyOption(
                new PropertyOption(
                        new PropertyOption2()
                                .intValue(15)));

    String json = mapper.writeValueAsString(initial);

    HelloRequest fromJson = mapper.readValue(json, HelloRequest.class);

    assertThat(fromJson).isEqualTo(initial); // Fails because propertyOption.isNullable is true in fromJson
}
Related issues/PRs
Suggest a fix

The deserialization logic constructs an empty PropertyOption (using the default constructor which initializes isNullable to true) and then calls setActualInstance. So options I can see is either change isNullable in setActualnstance or change deserialization logic to use the constructor that takes the instance as an argument.

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

No branches or pull requests

1 participant