使用Kotlin序列化,我想序列化和反序列化(到JSON)一个来自密封层次结构的带有类型参数的泛型数据类,但是,我得到了一个运行时异常。
要重现此问题:
import kotlinx.serialization.*
import kotlin.test.Test
import kotlin.test.assertEquals
/// The sealed hierarchy used a generic type parameters:
@Serializable
sealed interface Coded {
val description: String
}
@Serializable
@SerialName("CodeOA")
object CodeOA: Coded {
override val description: String = "Code Object OA"
}
@Serializable
@SerialName("CodeOB")
object CodeOB: Coded {
override val description: String = "Code Object OB"
}
/// Simplified class hierarchy
@Serializable
sealed interface NumberedData {
val number: Int
}
@Serializable
@SerialName("CodedData")
data class CodedData<out C : Coded> (
override val number: Int,
val info: String,
val code: C
): NumberedData
internal class GenericSerializerTest {
@Test
fun `polymorphically serialize and deserialize a CodedData instance`() {
val codedData: NumberedData = CodedData(
number = 42,
info = "Some test",
code = CodeOB
)
val codedDataJson = Json.encodeToString(codedData)
val codedDataDeserialized = Json.decodeFromString<NumberedData>(codedDataJson)
assertEquals(codedData, codedDataDeserialized)
}
}
在以下运行时异常中运行测试结果:
kotlinx.serialization.SerializationException: Class 'CodeOB' is not registered for polymorphic serialization in the scope of 'Coded'.
Mark the base class as 'sealed' or register the serializer explicitly.
这个错误消息对我来说没有意义,因为两个层次结构都被密封并标记为@Serializable
。
我不明白问题的根本原因-我需要显式地注册一个插件生成的序列化器吗?或者我需要滚动我自己的序列化器吗?为什么会这样?
我使用的是Kotlin1.7.20和kotlinx。序列化1.4.1
1条答案
按热度按时间avwztpqn1#
有关密封类状态的KotlinX序列化文档(* emphasis mine *):
你必须确保序列化对象的编译时类型是多态的,而不是具体的。
在下面的文档示例中,我们看到序列化子类而不是父类阻止了使用父(多态)类型对其进行反序列化。
在你的例子中,你有嵌套的多态类型,所以我认为这更加复杂。为了使序列化和反序列化工作,我尝试了很多方法,最后,我发现唯一的方法是:
1.删除CodedData上的泛型(以确保以多态方式解释
code
属性:1.编码时将编码数据对象强制转换为
NumberedData
,以确保触发多态性:使用基于您自己的单元测试的小主程序进行测试:
它打印: