提问人:Monica 提问时间:5/4/2022 最后编辑:Monica 更新时间:5/8/2022 访问量:867
Kotlin 中嵌套列表对象的多态反序列化
Polymorphic deserialization of nested list object in Kotlin
问:
尝试反序列化一个非常复杂的 json 字符串,我已经做了更简单的字符串,但我正在努力如何设置它。我还发现了一些关于简单多态反序列化的示例,但无法弄清楚如何使它适应这种更复杂的情况,其中我有不同的嵌套对象,其中一些是多态的,而另一些不是。任何帮助将不胜感激!
@Serializalbe
data class Object1(
@SerialName("id")
val id: String,
@SerialName("object2"),
val object2: List<Object2>
)
data class Object2(
@SerialName("name")
val name: String,
@SerialName("object2"),
val object3: List<Object3>
)
@Polymorphic
interface Object3: Parcelable {
val id: String
/**
* [Object3.Item1],
* [Object3.Item2]
*/
val type: Object3.Type
val data: Data
val options: List<Options>
}
@Serializable
@SerialName(type)
@Parcelize
data class Item1(
@SerialName("_version")
val version: String,
@SerialName("info")
override val info: AnotherPolyMorphicItem,
) : Object3 {
override val type: Type get() = Object3.Type.Item1
}
@Serializable
@SerialName(type)
@Parcelize
data class Item2(
@SerialName("_title")
val tile: String,
@SerialName("info")
val info: AnotherPolymorphicItem,
@SerialName("post")
val post: String
) : Object3 {
override val type: Type get() = Object3.Type.Item2
}
我为 Object3 反序列化构建了这个:
object Object3Json : SerializerContainer {
override val serializer =
Json {
isLenient = false
ignoreUnknownKeys = false
allowSpecialFloatingPointValues = true
useArrayPolymorphism = false
ignoreUnknownKeys = true
useAlternativeNames = false
classDiscriminator = "type"
serializersModule = SerializersModule {
polymorphic(Object3::class) {
subclass(Item1::class, Item1.serializer())
}
polymorphic(Object3::class) {
subclass(Item2::class, Item2.serializer())
}
}
}
}
我也一直在反序列化更简单的json字符串,如下所示:
object DefaultJson : SerializerContainer {
override val serializer: Json by lazy {
Json {
isLenient = false
useAlternativeNames = false
}
}
}
val responseObject = DefaultJson.serializer.decodeFromString(
ResponseObject.serializer(), payload
)
@Serializable
data class ResponseObject(
@SerialName("data1")
val data1: String,
@SerialName("data2")
val data2: String
)
我的问题是如何将更简单的反序列化与多态性相结合,以及如何反序列化为对象列表,就像我想反序列化 Object1 列表一样,我已经遵循了我能找到的抛出错误的示例。
答:
-1赞
AndrewL
5/4/2022
#1
我们的项目有一些多态序列化,但我不知道你是否认为它很复杂。我们已经用标准 Jackson 实现了所有的序列化,并仔细提示了 / 注解。@JsonTypeInfo
@JsonSubTypes
这是一个代码片段 - 通过在类中仅有一个类型指示符,我们就实现了往返序列化,而无需任何自定义序列化程序。在本例中,我们有 6 种类型的 Event,它们使用 3 个具体类之一(一些细节,如接口,为简洁起见省略了所有类字段):
enum class EventType(val eventClass: KClass<out Event>) {
CLINICIAN_MEMBER_CHANNEL_MESSAGE_TO_CLINICIAN(MemberClinicianMessageEvent::class),
CLINICIAN_MEMBER_CHANNEL_MESSAGE_TO_MEMBER(MemberClinicianMessageEvent::class),
MENTOR_MEMBER_CHANNEL_MESSAGE_TO_MENTOR(MentorMemberMessageEvent::class),
MENTOR_MEMBER_CHANNEL_MESSAGE_TO_MEMBER(MentorMemberMessageEvent::class),
CARD_ACTION_TO_MEMBER(CardActionEvent::class),
CARD_ACTION_TO_CLINICIAN(CardActionEvent::class),
}
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.EXISTING_PROPERTY,
property = "eventType",
visible = true
)
@JsonSubTypes(
JsonSubTypes.Type(name = "CLINICIAN_MEMBER_CHANNEL_MESSAGE_TO_CLINICIAN", value = MemberClinicianMessageEvent::class),
JsonSubTypes.Type(name = "CLINICIAN_MEMBER_CHANNEL_MESSAGE_TO_MEMBER", value = MemberClinicianMessageEvent::class),
JsonSubTypes.Type(name = "MENTOR_MEMBER_CHANNEL_MESSAGE_TO_MENTOR", value = MentorMemberMessageEvent::class),
JsonSubTypes.Type(name = "MENTOR_MEMBER_CHANNEL_MESSAGE_TO_MEMBER", value = MentorMemberMessageEvent::class),
JsonSubTypes.Type(name = "CARD_ACTION_TO_MEMBER", value = CardActionEvent::class),
JsonSubTypes.Type(name = "CARD_ACTION_TO_CLINICIAN", value = CardActionEvent::class),
)
data class MemberClinicianMessageEvent(
override val id: RULID,
override val eventType: EventType,
override val createdBy: SkinnyProfile,
...skip...
) : StackEvent
data class MentorMemberMessageEvent(
override val id: RULID,
override val eventType: EventType,
override val createdBy: SkinnyProfile,
...skip...
) : StackEvent
data class CardActionEvent(
override val id: RULID,
override val eventType: EventType,
override val createdBy: SkinnyProfile,
...skip...
) : StackEvent
eventClass
在第一个枚举中,序列化不需要,但允许我们在其他地方执行类型验证。
评论
0赞
Monica
5/4/2022
所以我有一个用 kotlinx 构建的多态反序列化器,问题是多态类深深地嵌套在 JSON 中。如果该类是唯一的 json,我可以进行 poly 反序列化。然而,事实并非如此,基本上假设数据类 object1 具有 val data: Object2 然后数据类 object2 具有 val item: Object3。然后数据类 Object3 有 val 的东西:Object4。则数据类 Object4 是子类型为 1 和 2 的多态类。所以我不知道如何反序列化整个JSON字符串。如果只给我一个 Object4 的 JSON,那么我使用 kotlinx 的多态反序列化器就可以工作了。
0赞
AndrewL
5/5/2022
也许 kotlinx 有一个功能限制。暂时尝试 Jackson:您只需要这样的代码:JsonMapper.builder().addModule(KotlinModule(strictNullChecks = true)).build()
1赞
Monica
5/6/2022
#2
所以这比我想象的要简单得多。在你进入多态类之前,它返回的内容看起来有点滑稽,但所有数据都可以使用我设置的数据类结构访问。
我创建了一个列表,然后稍微调整了响应以包含它,所以我现在有:dataClass
Object1
@Serializable
data class Object1List(
@SerialName("object1")
val object1: List<Object1>
)
然后我按如下方式对其进行反序列化,有效负载是我正在反序列化的 JSON 字符串。
val response = Object3Json.serializer.decodeFromString(Object1List.serializer(), payload)
评论