使用KClass引用作为具体化参数从JSON反序列化
我试图实现一个通用的序列化框架,使用kotlinx序列化将传出和传入的消息转换为json。我正在开发一个多平台的应用程序,所以我试图让它在KotlinJVM和KotlinJS上运行 为此,我在每条消息中添加了一个使用KClass引用作为具体化参数从JSON反序列化,json,kotlin,generics,kotlin-js,kotlinx.serialization,Json,Kotlin,Generics,Kotlin Js,Kotlinx.serialization,我试图实现一个通用的序列化框架,使用kotlinx序列化将传出和传入的消息转换为json。我正在开发一个多平台的应用程序,所以我试图让它在KotlinJVM和KotlinJS上运行 为此,我在每条消息中添加了一个type字段,并使用一个映射将每个type字符串映射到KClass。那张地图是什么类型的?它包含KClass对象,这些对象的类扩展了Message类,因此在java中,我将我的映射指定为 Map(json) } } } @可序列化 类ClientLoginMessage :Message
type
字段,并使用一个映射将每个type
字符串映射到KClass
。那张地图是什么类型的?它包含KClass
对象,这些对象的类扩展了Message类,因此在java中,我将我的映射指定为
Map(json)
}
}
}
@可序列化
类ClientLoginMessage
:Message(Message.getMessageTypeByClass()){}
创建序列化程序的映射,如类型:
val序列化程序:Map=mapOf(
ClientLoginMessage::类到ClientLoginMessage.serializer(),
Message::类到Message.serializer()的转换
)
按如下方式传入所需的序列化程序以Json.decodeFromString
:
fun fromJson(json:String):消息?{
val plainMessage=Json.decodeFromString(Json)//从Json获取类型字符串
return messageTypes.entries.find{it.value==plainMessage.type}?let{
//如何使用it.key中的KClass作为具体化参数?
decodeFromString(serializers.get(plainMessage.type)!!,Json)
}
}
您可能还想看看Kotlin内置的多态类处理:我最终只是按照您的建议使用了内置的多态性,从那时我阅读文档时就完全忘记了这一点。谢谢你仍然回答了我最初的问题,关于如何在任意类中做到这一点。
@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>()) {}