Openapi-generator: [BUG] Missing imports from generated API client

Created on 6 Feb 2020  路  3Comments  路  Source: OpenAPITools/openapi-generator

Bug Report Checklist

  • [X] Have you provided a full/minimal spec to reproduce the issue?
  • [X] Have you validated the input using an OpenAPI validator (example)?
  • [X] What's the version of OpenAPI Generator used?
  • [X] Have you search for related issues/PRs?
  • [X] What's the actual output vs expected output?
Description

Generator failing to include import when an Operation's response type is Map<List<Type>>.

For instance a function that returns Map<List<Option>> fails to include Option as part of the imports and the class becomes unable to compile.

See the yaml below for the input.

The following code is generated. There is a reference to Option in the code, but the import is not included.

/*
 * OpenAPI Test
 * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
 *
 * The version of the OpenAPI document: 1.0.0
 * 
 *
 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 * https://openapi-generator.tech
 * Do not edit the class manually.
 */


package com.test.resources;

import com.test.ApiCallback;
import com.test.ApiClient;
import com.test.ApiException;
import com.test.ApiResponse;
import com.test.Configuration;
import com.test.Pair;
import com.test.ProgressRequestBody;
import com.test.ProgressResponseBody;

import com.google.gson.reflect.TypeToken;

import java.io.IOException;



import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class OptionsApi {
    private ApiClient localVarApiClient;

    public OptionsApi() {
        this(Configuration.getDefaultApiClient());
    }

    public OptionsApi(ApiClient apiClient) {
        this.localVarApiClient = apiClient;
    }

    public ApiClient getApiClient() {
        return localVarApiClient;
    }

    public void setApiClient(ApiClient apiClient) {
        this.localVarApiClient = apiClient;
    }

    /**
     * Build call for getOptions
     * @param type  (optional)
     * @param _callback Callback for upload/download progress
     * @return Call to execute
     * @throws ApiException If fail to serialize the request body object
     * @http.response.details
     <table summary="Response Details" border="1">
        <tr><td> Status Code </td><td> Description </td><td> Response Headers </td></tr>
        <tr><td> 0 </td><td> default response </td><td>  -  </td></tr>
     </table>
     */
    public okhttp3.Call getOptionsCall(List<String> type, final ApiCallback _callback) throws ApiException {
        Object localVarPostBody = null;

        // create path and map variables
        String localVarPath = "/options";

        List<Pair> localVarQueryParams = new ArrayList<Pair>();
        List<Pair> localVarCollectionQueryParams = new ArrayList<Pair>();
        if (type != null) {
            localVarCollectionQueryParams.addAll(localVarApiClient.parameterToPairs("multi", "type", type));
        }

        Map<String, String> localVarHeaderParams = new HashMap<String, String>();
        Map<String, String> localVarCookieParams = new HashMap<String, String>();
        Map<String, Object> localVarFormParams = new HashMap<String, Object>();
        final String[] localVarAccepts = {
            "application/json"
        };
        final String localVarAccept = localVarApiClient.selectHeaderAccept(localVarAccepts);
        if (localVarAccept != null) {
            localVarHeaderParams.put("Accept", localVarAccept);
        }

        final String[] localVarContentTypes = {

        };
        final String localVarContentType = localVarApiClient.selectHeaderContentType(localVarContentTypes);
        localVarHeaderParams.put("Content-Type", localVarContentType);

        String[] localVarAuthNames = new String[] {  };
        return localVarApiClient.buildCall(localVarPath, "GET", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback);
    }

    @SuppressWarnings("rawtypes")
    private okhttp3.Call getOptionsValidateBeforeCall(List<String> type, final ApiCallback _callback) throws ApiException {


        okhttp3.Call localVarCall = getOptionsCall(type, _callback);
        return localVarCall;

    }

    /**
     * Get available options
     * 
     * @param type  (optional)
     * @return Map&lt;String, List&lt;Option&gt;&gt;
     * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body
     * @http.response.details
     <table summary="Response Details" border="1">
        <tr><td> Status Code </td><td> Description </td><td> Response Headers </td></tr>
        <tr><td> 0 </td><td> default response </td><td>  -  </td></tr>
     </table>
     */
    public Map<String, List<Option>> getOptions(List<String> type) throws ApiException {
        ApiResponse<Map<String, List<Option>>> localVarResp = getOptionsWithHttpInfo(type);
        return localVarResp.getData();
    }

    /**
     * Get available options
     * 
     * @param type  (optional)
     * @return ApiResponse&lt;Map&lt;String, List&lt;Option&gt;&gt;&gt;
     * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body
     * @http.response.details
     <table summary="Response Details" border="1">
        <tr><td> Status Code </td><td> Description </td><td> Response Headers </td></tr>
        <tr><td> 0 </td><td> default response </td><td>  -  </td></tr>
     </table>
     */
    public ApiResponse<Map<String, List<Option>>> getOptionsWithHttpInfo(List<String> type) throws ApiException {
        okhttp3.Call localVarCall = getOptionsValidateBeforeCall(type, null);
        Type localVarReturnType = new TypeToken<Map<String, List<Option>>>(){}.getType();
        return localVarApiClient.execute(localVarCall, localVarReturnType);
    }

    /**
     * Get available options (asynchronously)
     * 
     * @param type  (optional)
     * @param _callback The callback to be executed when the API call finishes
     * @return The request call
     * @throws ApiException If fail to process the API call, e.g. serializing the request body object
     * @http.response.details
     <table summary="Response Details" border="1">
        <tr><td> Status Code </td><td> Description </td><td> Response Headers </td></tr>
        <tr><td> 0 </td><td> default response </td><td>  -  </td></tr>
     </table>
     */
    public okhttp3.Call getOptionsAsync(List<String> type, final ApiCallback<Map<String, List<Option>>> _callback) throws ApiException {

        okhttp3.Call localVarCall = getOptionsValidateBeforeCall(type, _callback);
        Type localVarReturnType = new TypeToken<Map<String, List<Option>>>(){}.getType();
        localVarApiClient.executeAsync(localVarCall, localVarReturnType, _callback);
        return localVarCall;
    }
}

openapi-generator version

4.3.0-SNAPSHOT

OpenAPI declaration file content or url
openapi: 3.0.1
info:
  title: OpenAPI Test
  version: 1.0.0
servers:
- url: http://localhost:8080
paths:
  "/options":
    get:
      tags:
      - options
      summary: Get available options
      operationId: getOptions
      parameters:
      - name: type
        in: query
        schema:
          type: array
          items:
            type: string
      responses:
        default:
          description: default response
          content:
            application/json:
              schema:
                type: object
                additionalProperties:
                  type: array
                  items:
                    "$ref": "#/components/schemas/Option"
components:
  schemas:
    Option:
      type: object
      properties:
        value:
          type: string
          readOnly: true
        description:
          type: string
          readOnly: true
Command line used for generation
openapi-generator-cli generate -g kotlin-client -i test.yaml
Steps to reproduce
Related issues/PRs
Suggest a fix

Maybe pass in the Operations imports Set reference to the fromResponse method and add any arbitrary imports as needed.

Bug

Most helpful comment

I also have this issue, but with the java spring generator. Could these issues be related?

All 3 comments

I also have this issue, but with the java spring generator. Could these issues be related?

@u4842 I believe the issue you linked is related and not necessarily typescript, nor java-spring or kotlin-client specific. I believe the issue is actually buried deep in the DefaultCodegen parsing of Operations and this affects all languages.

As mentioned in the Suggest a fix section, I believe the additionalProperties on a map type don't get added to the imports Set and thus aren't included in the generated import list of the API. I suggested maybe passing that imports set down into the fromResponse function so they could be added as a one-off instead of adding a new property to the CodegenOperation.

Unfortunately, I'm not entirely familiar with this code, so was hoping a maintainer could delegate best course of action.

I'm also seeing some imports that are not reflected in the project's dependencies:

com.google.gson.reflect.TypeToken;
com.squareup.okhttp.Call
okio.BufferedSink
okio.Okio
org.threeten.bp.LocalDate

and many more. 5.0.0-beta2

/edit: I had to add:

compile group: 'com.google.code.gson', name: 'gson', version: '2.8.6'
compile group: 'com.squareup.okhttp', name: 'okhttp', version: '2.7.5'
compile group: 'com.squareup.okhttp', name: 'logging-interceptor', version: '2.7.5'
compile group: 'com.squareup.retrofit', name: 'retrofit', version: '1.9.0'
compile group: 'org.threeten', name: 'threetenbp', version: '1.4.0'
compile group: 'io.swagger.core.v3', name: 'swagger-annotations', version: '2.1.4'
compile group: 'io.gsonfire', name: 'gson-fire', version: '1.8.4'

to get it to compile. But many of those imports are unused.

Was this page helpful?
0 / 5 - 0 ratings