swagger-gradle-codegen icon indicating copy to clipboard operation
swagger-gradle-codegen copied to clipboard

Arrays handling seems bugged

Open krbob opened this issue 3 years ago • 4 comments

I found a bug when generating api for a service responsing with an array of objects. Generated code doesn't point to proper class definition (TestObject in the example below replaced with Any?) despite it was properly generated.

Input:

{
  "swagger": "2.0",
  "info": {
    "version": "1.0",
    "title": "test-swagger",
    "description": "https://test-swagger.com/"
  },
  "schemes": [
    "https",
    "http"
  ],
  "produces": [
    "application/json"
  ],
  "consumes": [
    "application/json"
  ],
  "paths": {
    "/api/test/swagger": {
      "get": {
        "tags": [
          "test-swagger"
        ],
        "summary": "Test swagger.",
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "Uniqe id.",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "properties": {
                "cities": {
                  "type": "array",
                  "items": {
                    "$ref": "#/definitions/TestObject"
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "definitions": {
    "TestObject": {
      "properties": {
        "name": {
          "type": "string"
        }
      }
    }
  }
}

Output:

package com.test.package.apis

import com.test.package.models.Any?
import retrofit2.http.GET
import retrofit2.http.Headers

@JvmSuppressWildcards
interface TestSwaggerApi {
    /**
     * Test swagger.
     * The endpoint is owned by defaultname service owner
     * @param id Uniqe id. (required)
     */
    @Headers(
        "Content-Type: application/json"
    )
    @GET("/api/test/swagger")
    suspend fun apiTestSwaggerGet(
        @retrofit2.http.Query("id") id: String
    ): Map<String, Any?>
}
package com.test.package.models

import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass

/**
 * @property name
 */
@JsonClass(generateAdapter = true)
data class TestObject(
    @Json(name = "name") @field:Json(name = "name") var name: String? = null
)

krbob avatar Sep 16 '21 12:09 krbob

The specs looks correct on my end. @macisamuele are you able to confirm? If so this could be an actual bug in the generator.

@krzybob Which version of the library are you using?

cortinico avatar Sep 17 '21 06:09 cortinico

@cortinico 1.4.1

krbob avatar Sep 17 '21 08:09 krbob

@cortinico, @krzybob I'll be checking this in the next days. I do have a suspect that the issue is caused by the handling of schemas without type property, but I need to verify it.

macisamuele avatar Sep 17 '21 12:09 macisamuele

swagger-gradle-codegen assumes a JSON Object in the response (due to moshi deserialisation). A JSON Object is typed as Map<String, Any?>. I'm not sure if this is fully advertised or even if this is still needed.

Focusing on API response JSON Schema

properties:
  cities:
    type: array
    items:
      $ref: '#/definitions/TestObject'

it does not even requires to be an object as [1,2,3] would be technically a valid schema.

I would suggest to add type: object into the response schema and check if the generated code is more in line with the expectations[1]. If so I think that we have a temporary workaround as well as a mire directive approach on dealing with the specific case.

[1] Unfortunately, I don't have a laptop with me, hence it is complex for me to verify the code within the next 2 weeks.

macisamuele avatar Sep 20 '21 14:09 macisamuele