Получить карту на сервере ktor с помощью kotlinx.serialization - PullRequest
0 голосов
/ 31 марта 2020

У меня есть сервер Ktor, работающий с kotlinx.serialization, так как он json (de) serializer Я отправляю своему Ktor сообщение, подобное этому:

{
  "Brick(partNumber=004229, partName=Sticker Sheet for Set 295-1, dataSource=Rebrickable, brickImage=null, categoryID=58)": 5
}

, которое является парой Int, и это class:

import kotlinx.serialization.Serializable

@Serializable
data class Brick(
    val partNumber: String,
    val partName: String,
    val dataSource: String,
    val brickImage: String?,
    val categoryID: Int?
)

Но я получаю эту ошибку

kotlinx.serialization.json.JsonDecodingException: Invalid JSON at 0: Expected '[, kind: MAP'
    at kotlinx.serialization.json.internal.JsonReader.fail(JsonReader.kt:293)

Что для меня означает, что kotlinx.serialization ожидает другой синтаксис для класса карты. Что странно для меня. Когда я меняю тип на List>, он выдает то же исключение, но с LIST вместо MAP. РЕДАКТИРОВАТЬ: При дальнейшей проверке, он ожидает [вместо {в начале строки. Моя (частичная) реализация приложения

fun Application.module(testing: Boolean = false) {
    install(ContentNegotiation) { serialization() }
    routing {
        route("user") {
            route("brick") {
                post {
                    call.request.queryParameters["userName"]
                        ?.let { userRepository.login(it) } // Someone else is still working login nvm this
                        ?.let { user ->
                            val bricks = call.receive<Map<Brick, Int>>() // This throws an error
                            userRepository.addBricks(user, bricks)
                            call.respond(HttpStatusCode.OK)
                        }
                        ?: call.respond(HttpStatusCode.Unauthorized)
                }
            }
        }
    }
}

Функция модернизации android, которая отправляет класс (с использованием GSON):

    @POST("/user/brick")
    suspend fun setBricksAmounts(
        @Query("userName")
        userName: String,
        @Body
        brickAmounts: Map<Brick, Int>
    )

1 Ответ

0 голосов
/ 31 марта 2020

Я думаю, что использование класса в качестве ключа не работает в сериализации kotlinx, и похоже, что этот класс просто сериализуется в строку, чтобы использовать его в качестве ключа

Вместо этого вы можете получить его как Map<String, Int> и затем запустите

bricks.mapKeys { (jsonString, number) ->
   Json(JsonConfiguration.Stable).parse(Brick.Serializer, jsonString)
}

или эквивалентный код Джексона, если хотите

...