微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 KClass 引用作为具体化参数从 JSON 反序列化

如何解决使用 KClass 引用作为具体化参数从 JSON 反序列化

我正在尝试实现一个通用的序列化框架,以使用 kotlinx 序列化将传出和传入的消息转换为 json。我正在开发一个多平台应用程序,所以我试图让它在 KotlinJVM 和 Kotlinjs 上运行。

为此,我向每条消息添加一个 type 字段,并使用将每个 type 字符串映射到 KClass 的映射。那张地图的类型是什么?它包含 KClass<> 对象,其类扩展 Message 类,因此在 java 中我将我的地图指定为 Map<KClass<? extends Message>,String>

我如何在 Kotlin 中做到这一点?

之后我需要根据消息的键和类型对消息进行序列化和反序列化。 Java 框架采用 Class 参数作为我想要反序列化/实例化的对象类型(例如 gson.fromJson(ClientMessage.class))。在 Kotlin 中,这是使用 reified 参数 Json.decodeFromString<Type> 完成的。我在编译时不知道消息的类型,只有对 KClass 的引用,我如何基于它实例化一个对象?

@Serializable
open class Message(val type: String) {

    companion object {
        val messageTypes: Map<KClass<out Message>,String> = mapOf(
            ClientLoginMessage::class to "clientLoginMessage",Message::class to "message"
        )

        inline fun <reified T> getMessageTypeByClass(): String = messageTypes[T::class]!! // utility for defining the type in the constructors of the individual messages
    }

    fun toJson() = Json.encodetoString(this)

    fun fromJson(json: String): Message? {
        val plainMessage = Json.decodeFromString<Message>(json) // get type string from json
        return messageTypes.entries.find { it.value == plainMessage.type }?.let {
            // how can I use the KClass from it.key as reified parameter?
            Json.decodeFromString<?????>(json) 
        }
    }
}

@Serializable
class ClientLoginMessage
         : Message(Message.getMessageTypeByClass<ClientLoginMessage>()) {}

解决方法

为类型创建序列化器的映射:

val serializers: Map<KClass<out Message>,KSerializer<out Message>> = mapOf(
            ClientLoginMessage::class to ClientLoginMessage.serializer(),Message::class to Message.serializer()
        )


像这样传入Json.decodeFromString所需的序列化程序:

fun fromJson(json: String): Message? {
        val plainMessage = Json.decodeFromString<Message>(json) // get type string from json
        return messageTypes.entries.find { it.value == plainMessage.type }?.let {
            // how can I use the KClass from it.key as reified parameter?
            Json.decodeFromString(serializers.get(plainMessage.type)!!,json)
        }
    }

您可能还想看看 Kotlin 内置的多态类处理:https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/polymorphism.md

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?