OpenAPITools / openapi-generator

OpenAPI Generator allows generation of API client libraries (SDK generation), server stubs, documentation and configuration automatically given an OpenAPI Spec (v2, v3)
https://openapi-generator.tech
Apache License 2.0
21.83k stars 6.58k forks source link

[BUG][JAVA] Compilation error for a `Map<String, Set<InnerEnum>>` due to incompatible types #19393

Open Bragolgirith opened 2 months ago

Bragolgirith commented 2 months ago
Description

I have the following schema that describes the different roles an employee can have in different projects as a map of collection of enum, e.g.:

    Employee:
      type: object
      properties:
        projectRoles:
          type: object
          additionalProperties:
            uniqueItems: true
            type: array
            items:
              type: string
              enum:
                - DEVELOPER
                - TESTER
                - OWNER

This works correctly with most generators, however the java generator seems to have some trouble with it and generates an invalid Employee.java class:

public class Employee {

  // ... truncated

  // This should be Map<String, Set<InnerEnum>> instead
  private Map<String, Set<String>> projectRoles = new HashMap<>();

  // ... truncated

  public Employee putProjectRolesItem(String key, Set<InnerEnum> projectRolesItem) {
    if (this.projectRoles == null) {
      this.projectRoles = new HashMap<>();
    }
    this.projectRoles.put(key, projectRolesItem); // Compiler error here due to the mismatching types
    return this;
  }
}

The compiler error is as follows

incompatible types: java.util.Set<org.openapitools.client.model.Employee.InnerEnum> cannot be converted to java.util.Set<java.lang.String>

Note that the issue only occurs for inline enums (i.e. InnerEnums); enum references work as expected.

openapi-generator version

Tested using openapi-generator version 7.8.0.

OpenAPI declaration file content

A gist with a minimal OpenAPI spec file to reproduce the issue can be found here.

Generation Details

I'm generating the Java client using the openapi-generator-maven-plugin as follows:

<plugin>
    <groupId>org.openapitools</groupId>
    <artifactId>openapi-generator-maven-plugin</artifactId>
    <version>7.8.0</version>
    <executions>
        <execution>
            <phase>generate-sources</phase>
            <goals>
                <goal>generate</goal>
            </goals>
            <configuration>
                <inputSpec>
                    ${project.basedir}/src/main/resources/employee-api.json
                </inputSpec>
                <generatorName>java</generatorName>
                <library>webclient</library>
                <generateModels>true</generateModels>
                <generateModelTests>false</generateModelTests>
                <generateApiTests>false</generateApiTests>
                <configOptions>
                    <useJakartaEe>true</useJakartaEe>
                </configOptions>
            </configuration>
        </execution>
    </executions>
</plugin>
Steps to reproduce
  1. Generate a Java client using the provided OpenAPI spec file
  2. Try to compile the generated client
Bragolgirith commented 2 months ago

I think the problem is in the DefaultCodegen#updateDataTypeWithEnumForMap method, on line 4278:

property.datatypeWithEnum = property.datatypeWithEnum.replace(", " + baseItem.baseType, ", " + toEnumName(baseItem));

This will correctly replace a non-parameterized value type, e.g.:

but it will fail to replace a parameterized value type, e.g.:

as it will try to match a ", String" pattern that doesn't exist.

One (naive) idea could be to simply use the following replacement instead, which should work with both parameterized and non-parameterized value types:

property.datatypeWithEnum = property.datatypeWithEnum.replace(baseItem.baseType + ">", toEnumName(baseItem) + ">")