Openapi-generator: [BUG][JavaSpring] using "oneof" does not generate "OneOf*.java" models (openapi-generator-maven-plugin 4.3.0/4.3.1)

Created on 30 Jun 2020  路  5Comments  路  Source: OpenAPITools/openapi-generator

Bug Report Checklist

  • [x] Have you provided a full/minimal spec to reproduce the issue?
  • [x] Have you validated the input using an OpenAPI validator (example)?
  • [x] What's the version of OpenAPI Generator used? (openapi-generator-maven-plugin 4.3.0 and 4.3.1)
  • [x] Have you search for related issues/PRs?
  • [x] What's the actual output vs expected output?
  • [ ] [Optional] Bounty to sponsor the fix (example)
Description

While generating code with oneOf two models as a response (or request body) with Spring generator (openapi-generator-maven-plugin) code for the oneOf model is not generated.
For the given spec below the only generated models are Model1 and Model2 but the interface uses a model named OneOfModel1Model2 and a file named OneOfModel1Model2.java is not generated which cause a compilation error:

import api.generated.models.OneOfModel1Model2;

. . .

@Validated
@Api(value = "Default", description = "the Default API")
public interface DefaultApi {

    /**
     * GET /test : Your GET endpoint
     *
     * @return OK (status code 200)
     */
    @ApiOperation(value = "Your GET endpoint", nickname = "getTest", notes = "", response = OneOfModel1Model2.class, tags={  })
    @ApiResponses(value = { 
        @ApiResponse(code = 200, message = "OK", response = OneOfModel1Model2.class) })
    @RequestMapping(value = "/test",
        produces = { "application/json" }, 
        method = RequestMethod.GET)
    ResponseEntity<OneOfModel1Model2> getTest();

}
openapi-generator version

Tried with openapi-generator-maven-plugin 4.3.0 and 4.3.1.

OpenAPI declaration file content or url
{
  "openapi": "3.0.0",
  "info": {
    "title": "testAPI",
    "version": "1.0"
  },
  "servers": [
    {
      "url": "http://localhost:3000"
    }
  ],
  "paths": {
    "/test": {
      "get": {
        "summary": "Your GET endpoint",
        "tags": [],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/Model1"
                    },
                    {
                      "$ref": "#/components/schemas/Model2"
                    }
                  ]
                }
              }
            }
          }
        },
        "operationId": "get-test"
      }
    }
  },
  "components": {
    "schemas": {
      "Model1": {
        "title": "Model1",
        "type": "object",
        "properties": {
          "id1": {
            "type": "string"
          }
        }
      },
      "Model2": {
        "title": "Model2",
        "type": "object",
        "properties": {
          "id2": {
            "type": "integer"
          }
        }
      }
    }
  }
}
Steps to reproduce

Plugin configuration

    <properties>
        <kotlin.vesion>1.3.41</kotlin.vesion>
        <pact.artifactory.folder />
        <!--openapi generator-->
        <openapi-generator.version>4.3.1</openapi-generator.version>
        <openapi-generator.resources>/src/main/resources</openapi-generator.resources>
        <openapi-generator.specfile>api.json</openapi-generator.specfile>
        <openapi-generator.language>spring</openapi-generator.language>
        <openapi-generator.datelibrary>java8</openapi-generator.datelibrary>
        <openapi-generator.basepackage>api</openapi-generator.basepackage>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.openapitools</groupId>
                <artifactId>openapi-generator-maven-plugin</artifactId>
                <version>${openapi-generator.version}</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                        <configuration>
                            <inputSpec>
                                ${project.basedir}${openapi-generator.resources}/${openapi-generator.specfile}
                            </inputSpec>
                            <output>${project.build.directory}/generated-sources</output>
                            <generatorName>${openapi-generator.language}</generatorName>
                            <skipValidateSpec>true</skipValidateSpec>
                            <configOptions>
                                <sourceFolder>.</sourceFolder>
                                <dateLibrary>java8</dateLibrary>
                                <interfaceOnly>true</interfaceOnly>
                                <skipDefaultInterface>true</skipDefaultInterface>
                                <useTags>true</useTags>
                            </configOptions>
                            <modelPackage>${openapi-generator.basepackage}.generated.models</modelPackage>
                            <apiPackage>${openapi-generator.basepackage}.generated.api</apiPackage>
                            <generateModelDocumentation>false</generateModelDocumentation>
                            <generateApiDocumentation>false</generateApiDocumentation>
                            <generateModelDocumentation>false</generateModelDocumentation>
                            <generateApiDocumentation>false</generateApiDocumentation>
                            <generateSupportingFiles>false</generateSupportingFiles>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

        </plugins>
    </build>

Thanks :)

Bug

Most helpful comment

Hello.
I am also getting the same.
I can only guess that the implementation for Spring should be a Response Entity containing an "Object" type as opposed to the generated model.

I could of course for now just have it return "Object" but then the other aspects like documentation and client library generation will not be as accurate.

Thanks.

Screenshot from 2020-06-30 15-29-25

Screenshot from 2020-06-30 15-30-04

'/purchases/{purchaseID}/payment-intent': parameters: - schema: type: string format: uuid name: purchaseID in: path required: true description: The ProductPurchaseID - UUID post: summary: Create a Payment Intent for a Product Purchase operationId: createPaymentIntentForPurchase responses: '201': description: Created content: application/json: schema: oneOf: - $ref: '#/components/schemas/StripePaymentIntent' description: |- Create a payment intent for the product purcahse for the UX to handle payment. For example, passing the psp=STRIPE parameter will create a Stripe-Payment Intent for the product purchase. parameters: - schema: type: string enum: - STRIPE - PAYPAL - SAGE in: query name: psp description: The payment service provider to use. required: true tags: - Web

Screenshot from 2020-06-30 15-30-38

All 5 comments

Seeing it as well

Hello.
I am also getting the same.
I can only guess that the implementation for Spring should be a Response Entity containing an "Object" type as opposed to the generated model.

I could of course for now just have it return "Object" but then the other aspects like documentation and client library generation will not be as accurate.

Thanks.

Screenshot from 2020-06-30 15-29-25

Screenshot from 2020-06-30 15-30-04

'/purchases/{purchaseID}/payment-intent': parameters: - schema: type: string format: uuid name: purchaseID in: path required: true description: The ProductPurchaseID - UUID post: summary: Create a Payment Intent for a Product Purchase operationId: createPaymentIntentForPurchase responses: '201': description: Created content: application/json: schema: oneOf: - $ref: '#/components/schemas/StripePaymentIntent' description: |- Create a payment intent for the product purcahse for the UX to handle payment. For example, passing the psp=STRIPE parameter will create a Stripe-Payment Intent for the product purchase. parameters: - schema: type: string enum: - STRIPE - PAYPAL - SAGE in: query name: psp description: The payment service provider to use. required: true tags: - Web

Screenshot from 2020-06-30 15-30-38

In order to get a OneOf* class you have to make it a named component, then reference that in schema with a $ref.

This seems to be a universal case for the plugin, an "inline" definition does not result in a generated class (with some few exceptions.)

@hrkristian Can you give an example of what the named component would look like in the oneOf case?

I tried the following and as a result I got 4 classes. ObjectA, ObjectC, and ObjectD are all as defined. ObjectB is a combination of ObjectA and ObjectB, containing properties from both, but without any "oneof" type validation nor any inheritance with ObjectC and ObjectD.

      "ObjectA": {
        "type": "object",
        "properties": {
          "FancyProperty": {
            "$ref": "#/components/schemas/ObjectB"
          }
        }
      },
      "ObjectB": {
        "oneOf": [
          {
            "type": "string"
          },
          {
            "$ref": "#/components/schemas/ObjectC"
          },
          {
            "$ref": "#/components/schemas/ObjectD"
          }
        ]
      },
      "ObjectC": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string"
          },
          "value": {
            "type": "object"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "ObjectD": {
        "type": "object",
        "properties": {
          "something": {
            "type": "string"
          }
        }
      }
Was this page helpful?
0 / 5 - 0 ratings

Related issues

guidoschreuder picture guidoschreuder  路  21Comments

wing328 picture wing328  路  25Comments

MartinDelille picture MartinDelille  路  35Comments

samarthgupta437 picture samarthgupta437  路  21Comments

pellyadolfo picture pellyadolfo  路  21Comments