0

我正在使用 1.0.0 版本的kotlin 序列化,但是当我尝试反序列化“灵活”数组时我被卡住了。

从我无法控制的后端 API 中,我得到一个包含不同类型对象的 JSON 数组。您将如何使用 kotlin 序列化反序列化它们?

例子

这是 API 的响应

[
  {
    "id": "test",
    "person": "person",
    "lastTime": "lastTime",
    "expert": "pro"
  },
  {
    "id": "test",
    "person": "person",
    "period": "period",
    "value": 1
  }
]
@Serializable
sealed class Base {
  @SerialName("id")
  abstract val id: String
  @SerialName("person")
  abstract val person: String
}

@Serializable
data class ObjectA (
 @SerialName("id") override val id: String,
 @SerialName("title") override val title: String,
 @SerialName("lastTime") val lastTime: String,
 @SerialName("expert") val expert: String
) : Base()

@Serializable
data class ObjectB (
 @SerialName("id") override val id: String,
 @SerialName("title") override val title: String,
 @SerialName("period") val period: String,
 @SerialName("value") val value: Int
) : Base()


执行以下代码会导致错误

println(Json.decodeFromString<List<Base>>(json))

错误Polymorphic serializer was not found for class discriminator

4

2 回答 2

1

当您说您不控制 API 时,是否是 Kotlin 序列化库从您的代码生成的 JSON?还是您想与自己的类型争吵?

默认情况下,密封类是通过向对象中的 JSON添加一个字段来处理的type,但它是Base类中的一个属性。在下一个示例中,它将向您展示如何添加@SerialName("owned")注释来说明type每个类对应的值,如果您可以将正确的值添加到您的类中,这可能会对您有所帮助吗?尽管在您的 JSON 示例中,两个对象都将“类型”作为它们的type...

如果您无法将 API 响应推送到正确的位置,您可能必须编写一个自定义序列化程序(这是您关心的反序列化部分)来解析事物并识别每个对象的外观,并构建适当的对象。

(我对图书馆什么的了解不多,只是想给你一些东西看,看看有没有帮助!)

于 2020-10-15T16:45:38.340 回答
1

@cactustictacs 解决方案非常接近。他说“默认情况下,密封类是通过向 JSON 添加类型字段来处理的”

但是因为我没有type属性,所以我需要一个其他字段来决定它应该是哪个子类。

在 Kotlin Serializer 中,您可以通过

 val format = Json {
    classDiscriminator = "PROPERTY_THAT_DEFINES_THE_SUBCLASS"
 }
 val contentType = MediaType.get("application/json")
 val retrofit = Retrofit.Builder()
                .baseUrl(baseUrl)
                .client(client)
                .addConverterFactory(format.asConverterFactory(contentType))
                .build()

你可以在哪里classDiscriminator输入你想要的属性。希望这对将来的其他人有所帮助。

于 2020-10-27T11:58:55.410 回答