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

1

14

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.

Multivibrator answered 13/8, 2021 at 14:10 Comment(2)
I'm afraid the generator will not create composite types itself. There would be multiple ways to do this anyway. It seems like an illusion that you won't have to change anything if that part of the api would change even if it would generate your composite class.Jarid
StackOverflow is not an issue tracker. You haven't asked a question, and you have simply pointed out a problem. We can't help you unless you ask a question.Guarino
M
0

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
Multivibrator answered 26/5, 2023 at 9:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.