OpenAPITools / OpenAPITools/openapi-generator

[REQ] [Java] [Spring] mixed OneOf support with JsonUnwrapped

Open
#23,759 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Enhancement: Feature
Dominant language
Java
Stars
26.8k
Forks
7.7k
PR merge metrics
PR metrics pending

Description

Is your feature request related to a problem? Please describe.

Support models with oneOf without discriminator combined with properties (or allOf)

For example:

components:
  schemas:
    Account:
      type: object
      properties:
        owner:
          type: string
        bank:
          $ref: '#/components/schemas/Bank'
      oneOf:
        - properties:
            bankNumber:
              type: string
            bic:
              type: string
        - properties:
            iban:
              type: string

Describe the solution you'd like

Create an property annotated with @JsonUnwrapped

class Account {
  String owner;
  
  @JsonUnwrapped
  BankWrapper oneOf;
}
In case of useOneOfInterfaces = false

Generate an class with the composition of the oneOf elements.

For example:

public class BankWrapper {
  private String bankNumber;
  private String bic;
  private String iban;
}
In case of useOneOfInterfaces = true

Generate an wrapper interface for the oneOf elements using the appropriate JsonCreator static factory.

For example:

interface BankWrapper {
  @JsonCreator
  static BankWrapper(...) {
     ....
  }
}

Describe alternatives you've considered

  • Use composition for the oneOf by merging the elements (not very obvious generated classes)
  • create a custom deserializer for Account (complex)
  • create a normalizer to extract the oneOf and annotate with a vendorExtension

Additional context

Jackson ``@JsonUnwrapped` allows serialization of this json:

{
  "owner": "John Doe",
  "iban": "BE0001119990000"
}

Deserialization is more limited. Custom deserializer or @JsonSubTypes are not supported by @JsonUnwrapped
@JsonCreator static factory does work.

Arguments for @JsonCreator are limited to indivual @JsonProperty arguments, JsonNode or Map.

A JsonMapper configured with a Mixin allows the deserialization:

    @JsonCreator
    static AccountOneOfWrapper valueOf(JsonNode node) {
        return MAPPER.treeToValue(node, AccountOneOfWrapper.class);
    }

    @JsonTypeInfo(use = JsonTypeInfo.Id.DEDUCTION)
    @JsonSubTypes({
        @JsonSubTypes.Type(value = AccountOneOf.class), 
        @JsonSubTypes.Type(value = AccountOneOf1.class)
    })
    static interface AccountOneOfWrapperMixin {

    }

mapper is:

MAPPER = JsonMapper.shared().rebuild()
  .addMixIn(AccountOneOfWrapper.class,  AccountOneOfWrapper.AccountOneOfWrapperMixin.class)
  .build();

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

No repository files or tests are named. Start by locating the Java/Spring generation paths for oneOf and existing JsonUnwrapped handling, then define coverage for both useOneOfInterfaces settings and verify generated Account/BankWrapper serialization and deserialization against the examples.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, openapi, spring
Domain
backend-api-design, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.