【发布时间】:2021-09-24 12:15:57
【问题描述】:
我有一个枚举,我想使用 kotlinx.serialization 从 JSON 反序列化,同时忽略未知值。这是枚举
@Serializable
enum class OperatingMode {
Off, On, Auto
}
我所说的忽略未知数的意思是,如果我在 JSON 对象中有一个或多个不在该枚举中的模式,它们应该被视为不存在:
{"foo":"bar","mode":"Banana"}
// same as
{"foo":"bar"}
{"modes":["Off","On","Banana"]}
// same as
{"modes":["Off","On"]}
我通过编写自定义序列化程序来实现这一点,但对于这样一个简单的任务来说似乎相当冗长
internal object OperatingModeSafeSerializer : KSerializer<OperatingMode?> {
override val descriptor = PrimitiveSerialDescriptor("OperatingMode", PrimitiveKind.STRING)
override fun serialize(encoder: Encoder, value: OperatingMode?) {
// safe because @Serializable skips null fields
encoder.encodeString(value!!.name)
}
override fun deserialize(decoder: Decoder): OperatingMode? {
val string = decoder.decodeString()
return try {
OperatingMode.valueOf(string)
} catch (_: Exception) {
null
}
}
}
internal object OperatingModeSafeListSerializer: KSerializer<List<OperatingMode>> {
private val delegateSerializer = ListSerializer(OperatingModeSafeSerializer)
override val descriptor = delegateSerializer.descriptor
override fun deserialize(decoder: Decoder): List<OperatingMode> {
return decoder.decodeSerializableValue(delegateSerializer).filterNotNull()
}
override fun serialize(encoder: Encoder, value: List<OperatingMode>) {
encoder.encodeSerializableValue(delegateSerializer, value)
}
}
然后在每个反序列化OperatingMode的对象中我可以添加
@Serializable(with = OperatingModeSafeSerializer::class) // or
@Serializable(with = OperatingModeSafeListSerializer::class)
忽略未知数。
问题
- 这是大量的代码。我希望有更多的枚举,我需要完全相同的行为,我真的不想为每个枚举复制粘贴。我不知道如何使这种方法通用,因为这些对象不能通用,
@Serializable(with = ...)需要一个编译时常量。 - 理想情况下,我希望将此行为封装在枚举本身中,这样任何反序列化
OperatingMode的操作都会忽略未知数。
【问题讨论】:
标签: kotlin serialization enums