Created by: hugo-ma-alves
Hello
I was having some difficulties generating the java (feign) client when the requestBody included the oneOf directive. Let me try to illustrate with an example using the following spec.
openapi: 3.0.1
info:
title: Sample OneOf
description: Sample OneOf
version: v1
servers:
- url: 'http://localhost:8080'
description: Generated server url
paths:
/pet:
post:
tags:
- creation
summary: Create a new Pet
operationId: create
parameters:
- name: Accept-Language
in: header
description: Language
schema:
type: string
enum:
- FR
- DE
- EN
requestBody:
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/Cat'
- $ref: '#/components/schemas/Dog'
- $ref: '#/components/schemas/Lizard'
x-one-of-name: Pet
responses:
'201':
description: The was created
components:
schemas:
Pet:
type: object
required:
- petType
properties:
petType:
type: string
discriminator:
propertyName: petType
mapping:
dog: Dog
cat: Cat
lizzard: Lizzard
Cat:
allOf:
- $ref: '#/components/schemas/Pet'
- type: object
properties:
name:
type: string
Dog:
allOf:
- $ref: '#/components/schemas/Pet'
- type: object
properties:
bark:
type: string
Lizard:
allOf:
- $ref: '#/components/schemas/Pet'
- type: object
properties:
lovesRocks:
type: boolean
And to generate the client I use the following command:
generate -i "sample.yml" -g java -o pet-client --additional-properties=library=feign
So for the first try I used the code on the master branch and I got the following API class:
public interface CreationApi extends ApiClient.Api {
/**
* Create a new Pet
*
* @param acceptLanguage Language (optional)
* @param UNKNOWN_BASE_TYPE (optional)
*/
@RequestLine("POST /pet")
@Headers({
"Content-Type: application/json",
"Accept: application/json",
"Accept-Language: {acceptLanguage}"
})
void create(@Param("acceptLanguage") String acceptLanguage, UNKNOWN_BASE_TYPE UNKNOWN_BASE_TYPE);
}
The generator couldn't extract the correct type that encapsulates the subtypes of the Pet, so it uses the default value "UNKNOWN_BASE_TYPE. I tracked this value to the line https://github.com/OpenAPITools/openapi-generator/blob/49f55b0d8e3a9531e3962bd831b74181ac71abd8/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java#L5971. By default if it doesn't have another value it uses this one. Not sure if it is related with this ticket https://github.com/OpenAPITools/openapi-generator/issues/7256
Then I tried to use the extension x-one-of-name to manually define the model name to "Pet". This type is correctly created as a Java class from where the subtypes extend. And I got the same result.
I searched the code and found the function that parses the requestBody: https://github.com/OpenAPITools/openapi-generator/blob/49f55b0d8e3a9531e3962bd831b74181ac71abd8/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java#L6022-L6025
It looks to me that it expects a $ref for the requestBody schema and it doesn't takes in consideration that it can contain a oneOf ( I believe it is called inline schema? not sure about the naming). I then ran the generator with the change included in this PR and I got the following API.
public interface CreationApi extends ApiClient.Api {
/**
* Create a new Pet
*
* @param acceptLanguage Language (optional)
* @param pet (optional)
*/
@RequestLine("POST /pet")
@Headers({
"Content-Type: application/json",
"Accept: application/json",
"Accept-Language: {acceptLanguage}"
})
void create(@Param("acceptLanguage") String acceptLanguage, Pet pet);
}
Now it uses the value of the extension as the Parameter name, and the client compiles correctly.
I saw some other issues that may be related with this topic, https://github.com/OpenAPITools/openapi-generator/issues/2892 https://github.com/OpenAPITools/openapi-generator/issues/5903 https://github.com/OpenAPITools/openapi-generator/issues/7256 And I believe there is also other option where the OneOf classes should be generated right? In this case the class OneOfDogCatLizard. But I couldn't generate these classes, do I need to pass diferente parameters to the generator cli?
So to sum up, if this change is technically correct I can complete the PR by fixing the unit tests and updating the documentation
Hugo
@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)
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. -
If contributing template-only or documentation-only changes which will change sample output, build the project beforehand. -
Run mvn clean package ./bin/generate-samples.sh ./bin/utils/export_docs_generators.sh
./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.1.x
,6.0.x
-
Copy the technical committee to review the pull request if your PR is targeting a particular programming language.