https://kotlinlang.org logo
#ktor
Title
# ktor
s

S.

04/15/2022, 6:37 PM
so
get().body<List<Class>>()
apparently also expects the json input to be an array and when it only returns one object I always run into
kotlinx.serialization.json.internal.JsonDecodingException: Expected start of the array '[', but had 'EOF' instead
is there a way around this other than catching the exception and
.body<Class>
?
a

Aleksei Tirman [JB]

04/16/2022, 5:50 AM
So an endpoint may return a JSON array or object?
s

S.

04/16/2022, 6:06 AM
Yes. it's like this:
Copy code
get("{id...}") {
            call.respond(call.parameters.getAll("id")?.map {
                WordService.fetchById(
                    it.toIntOrNull() ?: return@get call.respondText(
                        INVALID_ID,
                        status = HttpStatusCode.BadRequest
                    )
                ) ?: return@get call.respondText("No word with id $it", status = HttpStatusCode.NotFound)
            } ?: return@get call.respondText("No ids specified", status = HttpStatusCode.BadRequest))
        }
with only one id parameter it sends the single element of the list as an object
p

Paul Woitaschek

04/16/2022, 6:58 AM
Then let it return a JsonElement and do your magic based on that
s

S.

04/16/2022, 11:35 AM
sorry but how would I do this with ktor?
p

phldavies

04/16/2022, 8:31 PM
initially you'd need to get the JsonElement from ktor using
.get().body<JsonElement>()
and then use something that would handle the decoding of both a JsonArray and a JsonObject to a
List<MyClass>
. Something similar to this might help:
Copy code
private inline fun <reified T> JsonElement.asListOf(serializer: KSerializer<T> = serializer()) =
    when (this) {
        is JsonObject -> listOf(Json.decodeFromJsonElement(serializer, this))
        is JsonArray -> Json.decodeFromJsonElement(ListSerializer(serializer), this)
        else -> error("Unexpected element type - expected object or array")
    }
which would allow you to do
.body<JsonElement>().asListOf<MyClass>()