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