我想序列化Map,其中一个值类型是Pair。如何将这对注册为多态子类?
val module = SerializersModule {
polymorphic(Any::class) {
subclass(Int::class, PolymorphicPrimitiveSerializer(Int.serializer()))
subclass(String::class, PolymorphicPrimitiveSerializer(String.serializer()))
subclass(Pair::class, PolymorphicSerializer(Pair::class))
}
}
val format = Json { serializersModule = module }
val mm = mapOf<String, Any>()
.plus("int-int pair") to (5 to 10))
val jsoned = format.encodeToString(mm)
val mmDecoded = format.decodeFromString(jsoned)
require(mm==mmDecoded)应该编码到json,比如:
[{"first": "int-int pair",
"second":{"type": "Pair", "value":
{"first": {"type": Int, "value":5}, "second": {"type":Int, "value": 10}}}}]但会产生以下错误:
线程"main“中由:
:序列化程序引起的java.lang.ExceptionInInitializerError异常不能注册为多态序列化的子类,因为它的打开类型不是具体的。要处理多个层次结构,注册为基类。kotlinx.serialization.json.internal.PolymorphismValidator.checkKind(PolymorphismValidator.kt:41) at kotlinx.serialization.json.internal.PolymorphismValidator.polymorphic(PolymorphismValidator.kt:31) at kotlinx.serialization.modules.SerialModuleImpl.dumpTo(SerializersModule.kt:189) at kotlinx.serialization.json.JsonImpl.validateConfiguration(Json.kt:358) at kotlinx.serialization.json.JsonImpl.(Json.kt:352) at kotlinx.serialization.json.JsonKt.Json(Json.kt:189) at kotlinx.serialization.json.JsonKt.Json$default(Json.kt:185) at MainKt.(Main.kt:143)
发布于 2022-11-21 14:47:15
我通过提供自定义多态序列化程序来解决这个问题,类似于我如何序列化map:https://github.com/assafshouval/PolymorphicMapSerializer/blob/master/src/main/kotlin/Main.kt
发布于 2022-11-07 15:47:51
我无法使它与多态子类一起工作,但我认为这个特性并不适合与Any和原语一起使用(参见this question)。自定义序列化程序似乎是一种更合适和更简单的解决方案,与多态序列化不同,它不需要太多的自定义序列化代码:
@ExperimentalSerializationApi
class DynamicLookupSerializer: KSerializer<Any> {
override val descriptor: SerialDescriptor = ContextualSerializer(Any::class, null, emptyArray()).descriptor
@OptIn(InternalSerializationApi::class)
override fun serialize(encoder: Encoder, value: Any) {
val actualSerializer = encoder.serializersModule.getContextual(value::class) ?: value::class.serializer()
encoder.encodeSerializableValue(actualSerializer as KSerializer<Any>, value)
}
override fun deserialize(decoder: Decoder): Any {
return try {
PairSerializer(Int.serializer(), Int.serializer()).deserialize(decoder)
} catch (e: Throwable) {
try {
decoder.decodeInt()
} catch (e: Throwable) {
decoder.decodeString()
}
}
}
}
val module = SerializersModule {
contextual(Any::class, DynamicLookupSerializer())
contextual(Pair::class) {
PairSerializer(Int.serializer(), Int.serializer())
}
}
val format = Json { serializersModule = module }
val mm = mapOf<String, Any>()
.plus("int-int pair" to (5 to 10))
.plus("int" to 6)
.plus("string" to "some string")
.plus("another-int" to 86248726)
.plus("another-pair" to (56 to 961))
val jsoned = format.encodeToString(mm)
println(jsoned)
val mmDecoded = format.decodeFromString<Map<String, Any>>(jsoned)
require(mm==mmDecoded)在这个自定义序列化器中,我们通过value: Any类(value::class)查找序列化时,找到了它的实际序列化程序。因此,PairSerializer(Int.serializer(), Int.serializer())也必须注册,以便在DynamicLookupSerializer.serialize中找到它。反序列化时,我们一个接一个地尝试支持的序列化器(string、int和对int)。
我确实意识到,由于尝试捕获,这不是最好的解决方案,但它确实有效,而且很简单。
https://stackoverflow.com/questions/74291655
复制相似问题