【发布时间】:2021-01-23 15:03:17
【问题描述】:
我正在尝试实现一个通用的序列化框架,以使用 kotlinx 序列化将传出和传入的消息转换为 json。我正在开发一个多平台应用程序,所以我试图让它在 KotlinJVM 和 KotlinJS 上运行。
为此,我为每条消息添加了一个type 字段,并使用一个映射将每个type 字符串映射到KClass。那张地图的类型是什么?它包含 KClass<> 对象,其类扩展了 Message 类,因此在 java 中我将我的地图指定为
Map<KClass<? extends Message>, String>.
我如何在 Kotlin 中做到这一点?
之后我需要根据消息的键和类型对消息进行序列化和反序列化。 Java 框架为我想要反序列化/实例化的对象的类型(例如 gson.fromJson(ClientMessage.class))采用 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>()) {}
【问题讨论】:
标签: json kotlin generics kotlin-js kotlinx.serialization