Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG][KOTLIN] Kotlin client generation with generateOneOfAnyOfWrappers=true produces Java code in .kt file that does not compile in a Kotlin project #18890

Closed
5 of 6 tasks
martinLeht opened this issue Jun 10, 2024 · 5 comments · Fixed by #18891

Comments

@martinLeht
Copy link

Bug Report Checklist

  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator (example)?
  • Have you tested with the latest master to confirm the issue still exists?
  • Have you searched for related issues/PRs?
  • What's the actual output vs expected output?
  • [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description

I tested the latest openapi-generator latest (7.7.0-SNAPSHOT) that contains a fix related to better oneOf support for generated Kotlin client code generation. The latest Kotlin client generator generates code that does not compile in a Kotlin project when using new config-option generateOneOfAnyOfWrappers=true. Kotlin generator produces Java code among the Kotlin code which results in a .kt file that does not compile. This problem persists when generation is performed against an OpenAPI schema that uses oneOf and discriminator for polymorphism.

By simply looking at the mustache template files, one can see that there are variables declared in Java syntax and that some exceptions are thrown with "new" keyword that does not exist in Kotlin and thus does not compile. Below are some snippets and references to the templates:

...
 {{#isArray}}
                List<?> list = (List<?>) value.actualInstance // Java specific syntax
                if (list.get(0) is {{{items.dataType}}}) {
                     ...
                }
{{/isArray}}
...
  • The template for data classes kotlin-client/data_class.mustache contains the "new" keyword when exceptions are thrown, in addition to having JsonArray variable declarations that are written with Java syntax:
    • IllegalArgumentException thrown with "new" keyword on row 249
...
throw new IllegalArgumentException(String.format("Expected the field `{{{baseName}}}` to be an array in the JSON string but got `%s`", jsonObj["{{{baseName}}}"].toString()))
...
...
JsonArray jsonArray{{name}} = jsonObj.getAsJsonArray("{{{baseName}}}")
...
openapi-generator version

This issue currently on latest 7.7.0-SNAPSHOT version.

OpenAPI declaration file content or url
openapi: 3.0.3
info:
  title: test
  version: 1.0.0
  description: test
  license:
    name: Apache 2.0
    url: https://www.apache.org/licenses/LICENSE-2.0.html
servers:
  - url: https://petstore.swagger.io/v2
paths:
  /pets:
    patch:
      requestBody:
        content:
          application/json:
            schema:
              oneOf:
                - $ref: '#/components/schemas/Cat'
                - $ref: '#/components/schemas/Dog'
              discriminator:
                propertyName: pet_type
      responses:
        '200':
          description: Updated
components:
  schemas:
    Pet:
      type: object
      required:
        - pet_type
      properties:
        pet_type:
          type: string
      discriminator:
        propertyName: pet_type
    Dog:     # "Dog" is a value for the pet_type property (the discriminator value)
      allOf: # Combines the main `Pet` schema with `Dog`-specific properties
        - $ref: '#/components/schemas/Pet'
        - type: object
          # all other properties specific to a `Dog`
          required:
            - names
          properties:
            names:
              type: array
              items:
                type: object
                properties:
                  firstname:
                    type: string
                  lastname:
                    type: string
            bark:
              type: boolean
            breed:
              type: string
              enum: [Dingo, Husky, Retriever, Shepherd]
    Cat:     # "Cat" is a value for the pet_type property (the discriminator value)
      allOf: # Combines the main `Pet` schema with `Cat`-specific properties
        - $ref: '#/components/schemas/Pet'
        - type: object
          # all other properties specific to a `Cat`
          properties:
            hunts:
              type: boolean
            age:
              type: integer
Generation Details

Use latest generator CLI via docker: openapitools/openapi-generator-cli:latest

Use above provided OpenAPI YAML to reproduce (see detailed below).

Configuration options (additional-properties) for Kotlin client generation:

  • generateOneOfAnyOfWrappers=true
  • enumPropertyNaming=original
  • serializationLibrary=gson
Steps to reproduce

Run kotlin client generation command with latest openapi-generator-cli image against the OpenAPI YAML provided above with above additional properties described above:
docker run --rm -v "${PWD}:/local" openapitools/openapi-generator-cli:latest generate -i /local/pets.yaml -g kotlin -o /local/generated/kotlin --additional-properties=generateOneOfAnyOfWrappers=true,enumPropertyNaming=original,serializationLibrary=gson

Related issues/PRs

Bug was a result of PR: 353320c

Suggest a fix

Kotlin mustache templates should be fixed, so that there is only Kotlin syntax and no Java specific syntax. The above listed variable declarations and exception throwing should probably be fixed to Kotlin equivalent as follows:

  • Before (Java) -> After (Kotlin):
List<?> list = (List<?>) value.actualInstance // Java
-> val list = value.actualInstance as List<Any> // Kotlin


JsonArray jsonArray{{name}} = jsonObj.getAsJsonArray("{{{baseName}}}") // Java
-> val jsonArray{{name}} = jsonObj.getAsJsonArray("{{{baseName}}}") // Kotlin


throw new IllegalArgumentException(...) // Java
-> throw IllegalArgumentException(...) // Kotlin

@wing328
Copy link
Member

wing328 commented Jun 10, 2024

@martinLeht thank for reporting the issue.

I've filed #18891 to fix it

@martinLeht
Copy link
Author

martinLeht commented Jun 10, 2024

@martinLeht thank for reporting the issue.

I've filed #18891 to fix it

Thanks!

@wing328
Copy link
Member

wing328 commented Jun 12, 2024

PR merged. Please give it a try with the latest master. (snapshot version available in the project's readme)

@martinLeht
Copy link
Author

@wing328 Nice, it seems to be working regarding the problems I mentioned earlier, thanks!

I noticed tho another problem (possibly related to encoding on generation?). In the template kotlin-client/data_class.mustache we have the following jsonArray variable declaration and for-loop:

val jsonArray{{name}} = jsonObj.getAsJsonArray("{{{baseName}}}")
// validate the required field `{{{baseName}}}` (array)
for (i in 0 until jsonArray{{name}}.size()) {
              {{{items.dataType}}}.validateJsonElement(jsonArray{{name}}.get(i))
}

The above template produces uncompilable code, when the variable {{name}} = "data" in the OpenAPI spec. The generated code would look like this (uncompilable):

val jsonArray&#x60;data&#x60; = jsonObj.getAsJsonArray("data")
// validate the required field `data` (array) 
for (i in 0 until jsonArray&#x60;data&#x60;.size()) {
             <SOME_MODEL>.validateJsonElement(jsonArray&#x60;data&#x60;.get(i))
}

But when the {{name}} = "entities" or something else than "data", it generates code that is compilable and good:

val jsonArrayentities = jsonObj.getAsJsonArray("entities")
// validate the required field `entities` (array)
for (i in 0 until jsonArrayentities.size()) {
              <SOME_MODEL>.validateJsonElement(jsonArrayentities.get(i))
}

Should I make a separate issue with more details or is this enough?

@martinLeht
Copy link
Author

@wing328 made new issue related to the problem above: #18908

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

Successfully merging a pull request may close this issue.

2 participants