Skip to content

Conversation

martin-bucinskas
Copy link

@martin-bucinskas martin-bucinskas commented Nov 30, 2021

Updated SpringCodegen to allow the usage of oneOf when generating models with discriminators and without.

Fixes:

Generation of oneOf interfaces without discriminator

https://swagger.io/specification#discriminator-object states that oneOf can be used without a discriminator object.
We can utilise a feature brought in by jackson since version 2.12 to use deduction-based polymorphism.

It basically allows omitting of actual Type Id field or value, as long as the subtype can be deduced (@JsonTypeInfo(use=DEDUCTION)) from existence of fields. That is, every subtype has a distinct set of fields they included, and so during deserialization type can be uniquely and reliably detected.

By setting the x-deduction and x-deduction-model-names vendor extensions, we can set up the values that will be populated in the oneOf templates for a deduction based approach, where x-deduction is a flag used to switch between deduction and discriminator approach, and x-deduction-model-names is an array of the type names.

PR based on #10463 implementation.

PR checklist

  • Read the contribution guidelines.
  • Pull Request title clearly describes the work in the pull request and Pull Request description provides details about how to validate the work. Missing information here may result in delayed response from the community.
  • Run the following to build the project and update samples:
    ./mvnw clean package 
    ./bin/generate-samples.sh
    ./bin/utils/export_docs_generators.sh
    
    Commit all changed files.
    This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
    These must match the expectations made by your contribution.
    You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example ./bin/generate-samples.sh bin/configs/java*.
    For Windows users, please run the script in Git BASH.
  • File the PR against the correct branch: master (5.3.0), 6.0.x
  • If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.

@bbdouglas (2017/07) @sreeshas (2017/08) @jfiala (2017/08) @lukoyanov (2017/09) @cbornet (2017/09) @jeff9finger (2018/01) @karismann (2019/03) @Zomzog (2019/04) @lwlee2608 (2019/10) @nmuesch (2021/01)

- Adding support for oneOf with and without discriminators.
- Created oneof_interface.mustache template.
- Updating SpringCodegen with an implementation to add imports for one of interfaces.
…e of.

- Attempting to repair inline oneOf before calling the super.
- Post processing all oneOf models to add x-deduction and x-deduction-model-names vendor extensions.
- Composed schema defaults to having isMap set to true if it contains additional properties,
  this is not the case some times.
- Fixing the squashed imports.
- Removing extra space in between annotation and interface.
- If components are null, there is nothing to preprocess other than title etc.
- Adding some test cases for oneOf code generation.
- Running /bin/generate-samples.sh
- Running /bin/utils/export_docs_generators.sh

Signed-off-by: Martin <7595909+martin-bucinskas@users.noreply.github.com>
@weierstrass
Copy link

@martin-bucinskas Thank you for this implementation of oneOf support . I am also really interested in having this feature in the Spring/Java generator. I tested out your changes on a specification that I am working on and the generated code looked good. I am not a maintainer but for whatever it is worth.

If there is anything I can help with to finally have oneOf support, please let me know.

@jimsong
Copy link

jimsong commented Dec 18, 2021

I'd like to echo the sentiment that this is something that is badly needed. Hopefully it can be merged and released soon!

@SamD
Copy link

SamD commented Jan 10, 2022

Yep, just hit the same issue

cyberflohr pushed a commit to cyberflohr/openapi-generator that referenced this pull request Jan 23, 2022
@daviian
Copy link

daviian commented Feb 21, 2022

@martin-bucinskas Is there something I can support you with? This feature would be highly welcome :D

@martin-bucinskas
Copy link
Author

@martin-bucinskas Is there something I can support you with? This feature would be highly welcome :D

@daviian I'll have a look at at fixing the conflicts on this branch some time this weekend, this probably needs to have test cases updated that someone could take a look at. I'd love to get this feature in the openapi-generator too!

@ManuelTS
Copy link

ManuelTS commented Mar 1, 2022

Having the same issue, thanks for working on this guys!

ManuelTS pushed a commit to TailoredMediaProject/tm-annotation-store-api that referenced this pull request Mar 3, 2022
single values are treated as an array with one entry, see OpenAPITools/openapi-generator#10993
@feliperuiz
Copy link

https://swagger.io/specification#discriminator-object states that oneOf can be used without a discriminator object.

Doesn't the specification state that using oneOf without a discriminator only implies composition and, if meaning to use polymorphism, a discriminator is required? At least that's what I get when reading the second paragraph here:

While composition offers model extensibility, it does not imply a hierarchy between the models. To support polymorphism, the OpenAPI Specification adds the discriminator field. When used, the discriminator will be the name of the property that decides which schema definition validates the structure of the model. As such, the discriminator field MUST be a required field.

@martin-bucinskas
Copy link
Author

https://swagger.io/specification#discriminator-object states that oneOf can be used without a discriminator object.

Doesn't the specification state that using oneOf without a discriminator only implies composition and, if meaning to use polymorphism, a discriminator is required? At least that's what I get when reading the second paragraph here:

While composition offers model extensibility, it does not imply a hierarchy between the models. To support polymorphism, the OpenAPI Specification adds the discriminator field. When used, the discriminator will be the name of the property that decides which schema definition validates the structure of the model. As such, the discriminator field MUST be a required field.

I don't think that a discriminator should be mandatory in such cases.

https://spec.openapis.org/oas/v3.0.2#fixed-fields-20

In OAS 3.0, a response payload MAY be described to be exactly one of any number of types:

MyResponseType:
  oneOf:
  - $ref: '#/components/schemas/Cat'
  - $ref: '#/components/schemas/Dog'
  - $ref: '#/components/schemas/Lizard'

which means the payload MUST, by validation, match exactly one of the schemas described by Cat, Dog, or Lizard. In this case, a discriminator MAY act as a “hint” to shortcut validation and selection of the matching schema which may be a costly operation, depending on the complexity of the schema.

The use case for one of discriminator is not mandatory, but may be used to help resolve costly operations in a complex schema. However if the schema is not complex enough to require a discriminator, it should just be able to use a modern approach of deduction and generate valid code.

- Updated one-of-spring code to match the latest changes within master branch.
@smilep
Copy link

smilep commented Jan 2, 2023

This feature is badly needed in openapi-generator. OpenAPI spec though mentions discriminator must be provided but there is no validation as such and lots of OpenAPI contracts are using oneOf without discriminator. And this makes it impossible for the generated client or server to find the polymorphic reference and generated code simply doesn't work.

@martin-bucinskas Thank you for your work. I was actually planning to write this feature till I stumbled on this PR. Will you be able to please resolve conflicts in this PR soon? Let me know if any help needed.

@welshm @cachescrubber Do you agree with adding this feature to OpenAPI-generator?

@welshm
Copy link
Contributor

welshm commented Jan 2, 2023

This feature is badly needed in openapi-generator. OpenAPI spec though mentions discriminator must be provided but there is no validation as such and lots of OpenAPI contracts are using oneOf without discriminator. And this makes it impossible for the generated client or server to find the polymorphic reference and generated code simply doesn't work.

@martin-bucinskas Thank you for your work. I was actually planning to write this feature till I stumbled on this PR. Will you be able to please resolve conflicts in this PR soon? Let me know if any help needed.

@welshm @cachescrubber Do you agree with adding this feature to OpenAPI-generator?

I do agree with the feature - some of this may be resolved already by #11650 - so likely this needs a rebase to resolve conflicts and re-test.

Would also be good to include generated samples here to be able to see the output of the changes

@jpfinne
Copy link
Contributor

jpfinne commented Mar 18, 2025

@martin-bucinskas , @alexsuperdev @welshm @smilep @feliperuiz @daviian @ManuelTS @SamD @weierstrass @jimsong

Could you have a look this version of DEDUCTION of oneOf?
#20919 [Java] [Spring] Use deduction configOptions for oneOfInterfaces

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants