使用 Kotlinx.serialization 将 JSON 数组解析为 Map<String, String>

Posted

技术标签:

【中文标题】使用 Kotlinx.serialization 将 JSON 数组解析为 Map<String, String>【英文标题】:Parse a JSON array into Map<String, String> using Kotlinx.serialization 【发布时间】: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",这是一种更好的数据结构 不,我正在写客户端。服务器正在返回它,我无权访问它。 github.com/Kotlin/kotlinx.serialization/blob/master/docs/… 【参考方案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") 做得怎么样?我也有定义吗?

以上是关于使用 Kotlinx.serialization 将 JSON 数组解析为 Map<String, String>的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 kotlinx.serialization 部分解码 JSON 字符串?

Ktor 与 Kmongo 和 kotlinx.serialization

使用 kotlinx.serialization 在 ktor 服务器中接收 Map

在 Kotlin/Native 中使用 kotlinx.serialization 进行多态反序列化

如何将 Spring Boot 映射器从 Jackson 交换到 kotlinx.serialization

使用 Kotlinx.serialization 将 JSON 数组解析为 Map<String, String>