Skip to content

[BUG][Java] Custom object wrapped in Optional won't result JsonNullable with OpenApi 3.1 #22812

@teemupartanen-compile

Description

@teemupartanen-compile

Bug Report Checklist

  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator?
  • 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 OpenApi 3.1 I'm not able to generate a JsonNullable from Optional that wraps object of custom class. This is possible when using OpenApi 3.0. Built-in classes (Boolean, String etc.) and enums seem to work, but not more complex classes. See examples for more details.

Examples

####### Optional<String>
OpenApi 3.1 can behave like OpenApi 3.0.

With OpenApi 3.1 this

  @Schema(oneOf = {String.class, Null.class})
  private Optional<String> exampleStr;

generates this

  @jakarta.annotation.Nullable
  private JsonNullable<String> exampleStr = JsonNullable.<String>undefined();

which is what OpenApi 3.0 also looks like. With OpenApi 3.0 this

  @Schema(nullable = true)
  private Optional<String> exampleStr;

generates this

  @jakarta.annotation.Nullable
  private JsonNullable<String> exampleStr = JsonNullable.<String>undefined();

####### Optional<CustomEnum>
Enums seem to work in OpenApi 3.1 the same way they work in OpenApi 3.0.

With OpenApi 3.1 this

  @Schema(oneOf = {ExampleEnumm.class, Null.class})
  private Optional<ExampleEnumm> exampleEnumm;

  public enum ExampleEnumm {
    EXAMPLE_ONE,
    EXAMPLE_TWO
  }

generates this

  @jakarta.annotation.Nullable
  private JsonNullable<ExampleEnummEnum> exampleEnumm = JsonNullable.<ExampleEnummEnum>undefined();

  public enum ExampleEnummEnum {
    EXAMPLE_ONE(String.valueOf("EXAMPLE_ONE")),
    EXAMPLE_TWO(String.valueOf("EXAMPLE_TWO"));

    private String value;
    // rest is redacted, not relevant for this issue.
  }

which is identical result compared to OpenApi 3.0. With OpenApi 3.0 this

  @Schema(nullable = true)
  private Optional<ExampleEnumm> exampleEnumm;

  public enum ExampleEnumm {
    EXAMPLE_ONE,
    EXAMPLE_TWO
  }

generates this

  @jakarta.annotation.Nullable
  private JsonNullable<ExampleEnummEnum> exampleEnumm = JsonNullable.<ExampleEnummEnum>undefined();

  public enum ExampleEnummEnum {
    EXAMPLE_ONE(String.valueOf("EXAMPLE_ONE")),
    EXAMPLE_TWO(String.valueOf("EXAMPLE_TWO"));

    private String value;
    // rest is redacted, not relevant for this issue.
  }

####### Optional<CustomClazz>
With custom class the behavior differs very much between OpenApi 3.1 and 3.0.

With OpenApi 3.1 this

  @Schema(oneOf = {ExampleClazz.class, Null.class})
  private Optional<ExampleClazz> exampleClazz;

  @Data
  @Schema(name = "ExampleClazz")
  public class ExampleClazz {
    @Schema(oneOf = {String.class, Null.class})
    private Optional<@Size(min = 1) String> optionalStrOne;

    @Schema(oneOf = {String.class, Null.class})
    private Optional<@Size(min = 1) String> optionalStrTwo;
  }

generates (with warnings) this

  public static final String JSON_PROPERTY_EXAMPLE_CLAZZ = "exampleClazz";
  @jakarta.annotation.Nullable private MyDtoClazzExampleClazz exampleClazz;

which is different what OpenApi 3.0 produces. With OpenApi 3.0 this

  @Schema(nullable = true)
  private Optional<ExampleClazz> exampleClazz;

  @Data
  @Schema(name = "ExampleClazz")
  public class ExampleClazz {
    @Schema(nullable = true)
    private Optional<@Size(min = 1) String> optionalStrOne;

    @Schema(nullable = true)
    private Optional<@Size(min = 1) String> optionalStrTwo;
  }

generates this

  @jakarta.annotation.Nullable
  private JsonNullable<ExampleClazz> exampleClazz = JsonNullable.<ExampleClazz>undefined();
openapi-generator version

7.19.0, 7.18.0, 7.17.0

Generation Details

I'm using Gradle. The configs for generator:

    configOptions.set([
            dateLibrary                   : 'java8',
            useJakartaEe                  : 'true',
            hideGenerationTimestamp       : 'true',
            interfaceOnly                 : 'true',
            java8                         : 'true',
            library                       : 'webclient',
            useOptional                   : 'true',
            additionalModelTypeAnnotations: '@lombok.Data @lombok.Builder @lombok.AllArgsConstructor'
    ])
Steps to reproduce
Related issues/PRs
Suggest a fix

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