Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deserialisation of List<UUID> in body fails during runtime #112

Open
LukasForst opened this issue Oct 14, 2021 · 1 comment
Open

Deserialisation of List<UUID> in body fails during runtime #112

LukasForst opened this issue Oct 14, 2021 · 1 comment

Comments

@LukasForst
Copy link

LukasForst commented Oct 14, 2021

post fails to deserialise List<UUID> in body, even though Swagger knows that the correct type is UUID. Kotlin says it's UUID, however during runtime, it's String, which results in ClassCastException when accessing the element. My project is using latest Jackson.

Minimal working example:

fun NormalOpenAPIRoute.testRoute() {
    route("/test").post<Unit, String, List<UUID>> { _, listUuids ->
        println(listUuids.joinToString(separator = " - ") { it.toString() }) // access on the element throws java.lang.ClassCastException
        respond("OK")
    }
}

Request:

curl -X POST "http://localhost:8080/test" -H "accept: application/json" -H "Content-Type: application/json" -d "[\"3fa85f64-5717-4562-b3fc-2c963f66afa6\"]"

Debugger:
image

Exception:

java.lang.ClassCastException: class java.lang.String cannot be cast to class java.util.UUID (java.lang.String and java.util.UUID are in module java.base of loader 'bootstrap')
	at com.wire.troy.routing.ConversationRoutesKt$testRoute$1$1.invoke(ConversationRoutes.kt:81)
	at kotlin.text.StringsKt__AppendableKt.appendElement(Appendable.kt:85)
	at kotlin.collections.CollectionsKt___CollectionsKt.joinTo(_Collections.kt:3344)
	at kotlin.collections.CollectionsKt___CollectionsKt.joinToString(_Collections.kt:3361)
	at kotlin.collections.CollectionsKt___CollectionsKt.joinToString$default(_Collections.kt:3360)

And the openapi.json

{
  "/test": {
    "post": {
      "requestBody": {
        "content": {
          "application/json": {
            "schema": {
              "items": {
                "format": "uuid",
                "nullable": false,
                "type": "string"
              },
              "nullable": false,
              "type": "array"
            }
          }
        }
      },
      "responses": {
        "200": {
          "content": {
            "application/json": {
              "schema": {
                "nullable": false,
                "type": "string"
              }
            }
          },
          "description": "OK"
        }
      }
    }
  }
}
@kkalisz
Copy link

kkalisz commented Nov 4, 2021

To be honest this is not an open API generator issue. It is mostly related to generic types information erasure at runtime. Jackson can't get generic type information so it is not able to propper parse this type. This will not work for top-level generic objects. But it should be fine for such a case.
class UuidsList(val values: List<UUID>

But this will require changing payload from list of uuids, to object that contains a list of UUIDs

Another solution will be to use post "x-www-form-urlencoded" content type with key-value pairs. But this will look exactly the same as the previous example (UuidsList)

We can use inheritance to preserve generic type at runtime, But unfortunately, this will not work out of the box as code from DefaultCollectionSchemaProvider needs to be adjusted as for now it only handles current class generic arguments without supertype support.

class UuidsList: ArrayList<UUID> { }

I have created some dirty working solution
https://github.com/kkalisz/Ktor-OpenAPI-Generator/tree/generic_parameters
https://github.com/kkalisz/Ktor-OpenAPI-Generator/blob/generic_parameters/src/test/kotlin/com/papsign/ktor/openapigen/TopLevelGenericObjectRequestTest.kt

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants