2

我正在尝试使用 kotlinx @Serializable,但我遇到了这个问题:

我有以下课程:

@Serializable
sealed class GrandParent

第二个:

@Serializable
sealed class Parent() : GrandParent() {
       abstract val id: String
    }

第三个

@Serializable
data class Child(
   override val id: String, ....
): Parent()

我需要祖父母,因为我在另一个类中将它用作泛型类型,而这恰好也有对 GrandParent 类的引用

@Serializable
data class MyContent(
   override val id: String,
   ....
   val data: GrandParent, <- so it has a self reference to hold nested levels
...): Parent()

每次我尝试运行它时都会出现错误...

Class 'MyContent' is not registered for polymorphic serialization in the scope of 'GrandParent'.
Mark the base class as 'sealed' or register the serializer explicitly.

我使用 ktor 作为包装器,kotlin 1.5.10。我是根据https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/polymorphism.md#registered-subclasses做的

有任何想法吗?

4

1 回答 1

0

您应该使用您的密封类进行序列化和反序列化,以便 kotlin 序列化“知道”添加具有正确实现的鉴别器。默认情况下它type在 json 中搜索,但您可以使用 JsonBuilder 更改它:

Json {
  classDiscriminator = "class"
}

这是一个例子:

@Serializable
sealed class GrandParent

@Serializable
sealed class Parent : GrandParent() {
  abstract val id: String,
}

@Serializable
data class Child(
  override val id: String,
): Parent()

@Serializable
data class MyContent(
  override val id: String,
  val data: GrandParent,
): Parent()

fun main() {
  val test = MyContent(id = "test", data = Child(id = "child"))

  val jsonStr = Json.encodeToString(GrandParent.serializer(), test)
  println("Json string: $jsonStr")

  val decoded = Json.decodeFromString(GrandParent.serializer(), jsonStr)
  println("Decoded object: $decoded")
}

结果在控制台:

Json string: {"type":"MyContent","id":"test","data":{"type":"Child","id":"child"}}
Decoded object: MyContent(id=test, data=Child(id=child))

编码和解码也可以这样写(但在幕后它将使用反射):

val jsonStr = Json.encodeToString<GrandParent>(test)
println("Json string: $jsonStr")

val decoded = Json.decodeFromString<GrandParent>(jsonStr)
println("Decoded object: $decoded")
于 2021-06-22T14:21:28.390 回答