Skip to content
GitLab
Projects Groups Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in / Register
  • O openapi-generator
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 3,476
    • Issues 3,476
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 402
    • Merge requests 402
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Packages and registries
    • Packages and registries
    • Package Registry
    • Infrastructure Registry
  • Monitor
    • Monitor
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • OpenAPI Tools
  • openapi-generator
  • Merge requests
  • !8423

[Generator][WIP]Extract schema name for requestBody when using oneOf

  • Review changes

  • Download
  • Email patches
  • Plain diff
Closed Administrator requested to merge github/fork/hugo-ma-alves/feature/requestbody-inline-model into master Jan 12, 2021
  • Overview 0
  • Commits 1
  • Pipelines 0
  • Changes 1

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
    to update all Petstore samples related to your fix. 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.1.x, 6.0.x
  • Copy the technical committee to review the pull request if your PR is targeting a particular programming language.
Assignee
Assign to
Reviewers
Request review from
Time tracking
Source branch: github/fork/hugo-ma-alves/feature/requestbody-inline-model