【问题标题】:Parse a JSON array into Map<String, String> using Kotlinx.serialization使用 Kotlinx.serialization 将 JSON 数组解析为 Map<String, String>
【发布时间】:2019-09-04 14:59:53
【问题描述】:

我正在编写一个 Kotlin 多平台项目 (JVM/JS),我正在尝试使用 Kotlinx.serialization 将 HTTP Json 数组响应解析为 Map

JSON 是这样的:

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

到目前为止,我能够将 JSON 作为字符串获取,但我找不到任何文档来帮助我构建地图或其他类型的对象。所有这些都说明了如何序列化静态对象。

我不能使用@SerialName,因为密钥不固定。

当我尝试返回 Map&lt;String, String&gt; 时,我收到此错误:

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

最后,我想获得Map&lt;String, String&gt; 或List&lt;MyObject&gt;,我的对象可能是MyObject(val id: String, val value: String)

有没有办法做到这一点? 否则我只想写一个字符串阅读器来解析我的数据。

【问题讨论】:

  • 是否有可能在 json 中得到重复的键?
  • 所有键都是唯一的,值可以重复
  • 如果有机会重构您的 json,请尝试将所有对象放在一个对象中,例如 {"someKey": "someValue", "otherKey": "otherValue"},这是一种更好的数据结构
  • 不,我正在写客户端。服务器正在返回它,我无权访问它。

标签: json kotlin kotlin-multiplatform kotlinx.serialization


【解决方案1】:

您可以像这样实现自己的简单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}") }
}

【讨论】:

  • 完美运行!!我正在研究的解决方法是使用 expect class 解析器并在 jvm 中使用 klaxon(我完成了)和在 js 中使用 JSON.parse 编写这两种实现,但这涵盖了这两种情况。谢谢!
  • 嘿伙计,SerialClassDescImpl("JsonMap") 做得怎么样?我也有定义吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-20
  • 2022-09-23
  • 2013-08-27
  • 2023-04-06
  • 1970-01-01
相关资源
最近更新 更多