Разобрать массив JSON в Mapиспользуя Kotlinx.serialization - PullRequest
2 голосов
/ 14 апреля 2019

Я пишу мультиплатформенный проект Kotlin (JVM / JS) и пытаюсь проанализировать ответ массива HTTP Json в Map, используя Kotlinx.serialization

JSON выглядит примерно так:

[{"someKey": "someValue"}, {"otherKey": "otherValue"}, {"anotherKey": "randomText"}]

Пока что я могу получить этот JSON как String, но я не могу найти какую-либо документацию, чтобы помочь мне построить Map или другой тип объекта.Все это говорит о том, как сериализовать статические объекты.

Я не могу использовать @SerialName, потому что ключ не зафиксирован.

Когда я пытаюсь вернуть Map<String, String>, я получаю этоошибка:

Can't locate argument-less serializer for class kotlin.collections.Map. For generic classes, such as lists, please provide serializer explicitly.

В конце я бы хотел получить Map<String, String> или List<MyObject>, где мой объект мог бы быть MyObject(val id: String, val value: String)

Есть ли способ сделатьтот?В противном случае, я просто пишу String reader, чтобы иметь возможность анализировать мои данные.

1 Ответ

1 голос
/ 14 апреля 2019

Вы можете реализовать свой собственный простой DeserializationStrategy, например:

object JsonArrayToStringMapDeserializer : DeserializationStrategy<Map<String, String>> {

    override val descriptor = SerialClassDescImpl("JsonMap")

    override fun deserialize(decoder: Decoder): Map<String, String> {

        val input = decoder as? JsonInput ?: throw SerializationException("Expected Json Input")
        val array = input.decodeJson() as? JsonArray ?: throw SerializationException("Expected JsonArray")

        return array.map {
            it as JsonObject
            val firstKey = it.keys.first()
            firstKey to it[firstKey]!!.content
        }.toMap()


    }

    override fun patch(decoder: Decoder, old: Map<String, String>): Map<String, String> =
        throw UpdateNotSupportedException("Update not supported")

}


fun main() {
    val map = Json.parse(JsonArrayToStringMapDeserializer, data)
    map.forEach { println("${it.key} - ${it.value}") }
}
...