javaopenapiopenapi-generator

openapi-generator-maven-plugin (Java) does not handle allOf properly


With org.openapitools:openapi-generator-maven-plugin, I have noticed that using allOf composed of multiple objects in a response does not generate a class combining these multiple objects. Instead it uses the first class defined in the allOf section.

Here is a minimal example (openapi.yaml) :

openapi: 3.0.0
info:
  title: Test
  version: v1
paths:
  /test:
    get:
      operationId: get
      responses:
        '200':
          description: Get
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/A'
                  - $ref: '#/components/schemas/B'
components:
  schemas:
    A:
      type: object
      properties:
        attA:
          type: string
    B:
      type: object
      properties:
        attB:
          type: integer

When generating the classes in Java via :

mvn org.openapitools:openapi-generator-maven-plugin:5.2.0:generate \
    -Dopenapi.generator.maven.plugin.inputSpec=openapi.yaml \
    -Dopenapi.generator.maven.plugin.generatorName=java

It shows a warning:

[WARNING] allOf with multiple schemas defined. Using only the first one: A

As expected, it generates classes A and B. But, when calling get(), the value returned by the call is of type A:

DefaultApi api = new DefaultApi();
A a = api.get();

Instead, I would have expected a composite object containing A and B properties (attA and attB), like this (result from https://editor.swagger.io/):

Result on swagger editor

I have created an issue on GitHub, but hopefully someone here may have had the same issue and managed to fix it.

Also, I can't modify the openapi.yaml file because it's an OpenAPI spec provided by an API I have to call, so modifying it would make no sense and will make it so difficult to manage if their OpenAPI spec change over time.


Solution

  • Version 6.0.0 of openapi-generator-maven-plugin solves the issue by generating a class (Get200Response) composed of the two objects A and B. After generating the classes using:

    mvn org.openapitools:openapi-generator-maven-plugin:6.0.0:generate \
        -Dopenapi.generator.maven.plugin.inputSpec=openapi.yaml \
        -Dopenapi.generator.maven.plugin.generatorName=java
    

    I can see that new Get200Response class:

    package org.openapitools.client.model;
    
    // ...
    
    public class Get200Response {
      public static final String SERIALIZED_NAME_ATT_A = "attA";
      @SerializedName(SERIALIZED_NAME_ATT_A)
      private String attA;
    
      public static final String SERIALIZED_NAME_ATT_B = "attB";
      @SerializedName(SERIALIZED_NAME_ATT_B)
      private Integer attB;
    
      // ...
    }
    

    And I was able to make the following code work. In that example, I have a dummy webserver listening on port 5000 and defining a /test endpoint returning {"attA": "hello", "attB": 1}.

    package org.example;
    
    import org.openapitools.client.ApiClient;
    import org.openapitools.client.ApiException;
    import org.openapitools.client.api.DefaultApi;
    import org.openapitools.client.model.Get200Response;
    
    public class Main {
      public static void main(String[] args) throws ApiException {
        ApiClient apiClient = new ApiClient();
        apiClient.setBasePath("http://localhost:5000");
    
        DefaultApi api = new DefaultApi(apiClient);
        Get200Response r = api.get();
        System.out.println(r.getAttA());
        System.out.println(r.getAttB());
      }
    }
    

    This successfully prints:

    hello
    1