How to use OpenAPI "oneOf" property with openapi-generator-maven-plugin when generating Spring code
Asked Answered
S

4

32

I am developing an application with an Angular frontend and RESTful Spring Boot Backend

I found this very handy maven plugin openapi-generator-maven-plugin from org.openapitools. With its code generation capability, it helps enforce a "contract first" approach between the frontend and backend for our API. But our swagger file uses "oneOf" property in the requestBody and responseBody definitions. I've tried to generate Spring code from this, but the generated Java class has missing imports:

import com.pack.api.dto.OneOfLatteCoffeAmericanoCoffe;
import com.pack.api.dto.UNKNOWN_BASE_TYPE;

Is there away to cofigue the plugin to work with Swagger's oneOf property? I'm usig Spring Boot 2.3.1, Swagger 3.0 and Openapi-generator-maven-plugin 4.3

Sheepcote answered 6/7, 2020 at 16:14 Comment(1)
The UNKNOWN_BASE_TYPE issue has been fixed with better inline schema handling in openapi-generator v6.0.0 release. Please give it a try and let us know if you're seeing the same issue via github.com/openapitools/openapi-generator/issues/newJobholder
C
27

Currently, openapi-generator doesn't support oneOf. This is a capability that had been newly introduced with OpenAPI v3 (FYI, only v2 and below are called "Swagger", it has then been renamed to OpenAPI). There are various generators (Java, Spring, lots of other languages). I have seen that contributions have been made during this year to enable oneOf support.

To sum up, it looks like you have to wait a bit more until you can exploit this feature of the OpenAPI v3 spec using the generator for Spring.

Edit: It's also listed on the "short term roadmap":

OAS3.0 features support: anyOf, oneOf, callbacks, etc

Claar answered 21/10, 2020 at 15:53 Comment(2)
I have been battling to generate a PHP client for an API that heavily uses anyOf and oneOf. After some googling and finding suprisingly few stack overflow questions arround this topic, I guess that support for polymorphism really is a strongly WIP topic for code generation?Marc
Just ran into this issue too :(Traveler
D
27

If you can modify your swagger, you may replace the oneOf with a reference to an abstract type.

For example, if your swagger looks like this :

components:
  schemas:
    'Parent':
      'vehicle':
        oneOf:
        - type: object
          properties:
            'car_property':
              type: string
        - type: object
          properties:
            'truck_property':
              type: string

You can modify it like that :

components:
  schemas:
    'Parent':
      type: object
      properties:
        'vehicle':
          $ref: '#/components/schemas/Vehicle'
    #---------------------------------------------------------------------------
    # Abstract class with discriminator 'vehicle_type'
    #---------------------------------------------------------------------------
    'Vehicle':
      type: object
      properties:
        'vehicle_type':
          type: string
          enum: [ 'CAR', 'TRUCK' ]
      discriminator:
        propertyName: vehicle_type
        mapping:
          'CAR': '#/components/schemas/Car'
          'TRUCK': '#/components/schemas/Truck'
    #---------------------------------------------------------------------------
    # Concrete classes
    #---------------------------------------------------------------------------
    'Car':
      allOf:
      - $ref: "#/components/schemas/Vehicle"
      - type: object
        properties:
          'car_property':
            type: string
    'Truck':
      allOf:
      - $ref: "#/components/schemas/Vehicle"
      - type: object
        properties:
          'truck_property':
            type: string

This swagger modification makes the generator work. It handles the same JSON objects though I am not 100% sure it is semanticaly equivalent in OpenAPI specification.

Descriptive answered 21/4, 2021 at 14:24 Comment(4)
When trying this solution, I am still getting: @JsonSubTypes({ @JsonSubTypes.Type(value = ERRORUNKNOWN.class, name = "Obj1"), @JsonSubTypes.Type(value = ERRORUNKNOWN.class, name = "Obj2"), }) in the abstract model, which is failing compilation.Sedulous
Hmm, it compiled but the compiled schema does not look correct, just says there is an object called 'discriminator' but nothing exist inside said object. Also this approach I don't think works if the property to switch on is an external one from the schema which it is in my situation and I can't control thatSet
This is the only solution that worked for me. Even when using the openapi-generator-maven-plugin v6.6.0, it didn't correctly interpret oneOf/anyOfSendal
As a sidenote – Redocly, the authors of a popular OpenAPI docs rendering tool, advise to use the discriminator only if the benefits outweight the added complexity: redocly.com/docs/resources/discriminator/…Claar
J
8

We've added better oneOf and anyOf support to some generators such as java (okhttp-gson, jersey2, native), csharp-netcore, Go, PowerShell, R and more. Please give it a try with the latest master. SNAPSHOT versions can be found in the project's README: https://github.com/OpenAPITools/openapi-generator/

Jobholder answered 25/10, 2020 at 9:40 Comment(5)
maven available 5.1.1 does not support oneof and anyof code generation. 5.2.0-SNAPSHOT and 6.0.0-SNAPSHOT are not available on maven . How are you suggesting to try these two version if they are supporting oneof? Have to use this utility in production code.Tanyatanzania
Please mention that the csharp-netcore generator also works for older frameworks too. We wasted a lot of time on this.Interracial
v6.2.0 should have better for oneOf in the spring generator. Please give it a try.Jobholder
@WilliamCheng v6.2.0 with Spring generates something like this: List<ParentEntityInner> for this items: oneOf: - $ref:Conah
Actually that is an interface. It also generates the concrete class so that is fine..Conah
E
0

I using @openapitools/openapi-generator-cli and i tried this java snapshot https://oss.sonatype.org/content/repositories/snapshots/org/openapitools/openapi-generator-cli/6.0.0-SNAPSHOT/openapi-generator-cli-${versionName}.jar and it worked for me.

Just need setup openapitools.json like this -

{
  "$schema": "./node_modules/@openapitools/openapi-generator-cli/config.schema.json",
  "spaces": 2,
  "generator-cli": {
    "version": "6.0.0-20211025.061654-22",
    "repository": {
      "downloadUrl": "https://oss.sonatype.org/content/repositories/snapshots/org/openapitools/openapi-generator-cli/6.0.0-SNAPSHOT/openapi-generator-cli-${versionName}.jar"
    }
  }
}
Ecstatic answered 12/5, 2022 at 8:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.