Kotlin 反序列化 - JSON 数组到多个不同的对象

Kotlin Deserialization - JSON Array to multiple different objects

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

从我无法控制的后端 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

当您说您无法控制 API 时,JSON 是否是由 Kotlin 序列化库从您的代码生成的?还是您想将其纳入您自己的类型?

默认情况下,密封的 class 是 handled by adding a type field to the JSON,您的对象中有它,但它是 Base class 中的 属性。在下一个示例中,它向您展示了如何添加 @SerialName("owned") 注释来说明每个 class 对应的 type 值,如果您可以将正确的注释添加到 class是吗?尽管在您的 JSON 示例中,两个对象的 type...

都具有“类型”

如果您不能将 API 响应推到正确的位置,您可能必须编写一个 custom serializer(这是您关心的反序列化部分)来解析事物并识别每个object 看起来像,并构造合适的。

(我不太了解图书馆或其他任何东西,只是想给你一些东西看看,看看是否有帮助!)

@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 中输入您想要的 属性。希望这对以后的其他人有所帮助。