我有以下密封接口(简化示例):
sealed interface Validation { val result: Int }
...它由几个枚举实现-每个枚举用于一个特定的应用程序。举例来说:
@Serializable(with = BoxedSerializer) // one of my attempts, see below
enum class AccountValidation(override val result: Int): Validation {
UNKNOWN(10),
BLOCKED(20),
OK(30)
}
@Serializable(with = BoxedSerializer) // one of my attempts, see below
enum class PasswordValidation(override val result: Int): Validation {
SHORT(10),
WEAK(20),
OK(30)
}
我想在可序列化的API类型中多态地使用这个枚举,如下所示:
@Serializable
data class ValidationResult(
val userName: String,
val validation: Validation
)
我在JVM上使用Kotlin1.7.21和Kotlin序列化1.4.1。开箱即用,这种设置不起作用,因为枚举被序列化为基本类型,没有type
字段用于多态序列化。我尝试了其他几种尝试:
- 通过代理类进行序列化,正如官方文档中所描述的,似乎不适用于枚举--我最终得到了一个堆栈溢出,可能是由于错误的递归。
- 自定义序列化为described here会导致内部编译器错误。
- 在泛型 Package 类中替代序列化(参见下面的示例代码):这也会因内部编译器错误而失败。
@Serializable
@SerialName("Validation")
data class ValidationBox<T : Validation>(val code: T)
class BoxedSerializer<T : Validation>(private val validationSerializer: KSerializer<T>) : KSerializer<T> {
private val boxSerializer = ValidationBox.serializer(validationSerializer)
override val descriptor: SerialDescriptor = boxSerializer.descriptor
override fun serialize(encoder: Encoder, value: T) {
val boxed = ValidationBox(value)
encoder.encodeSerializableValue(boxSerializer, boxed)
}
override fun deserialize(decoder: Decoder): T {
val boxed: ValidationBox<T> = decoder.decodeSerializableValue(boxSerializer)
return boxed.code
}
}
@Test
fun `polymorphically serialize and deserialize`() {
val validation: Validation = AccountValidation.BLOCKED
val validationJson = Json.encodeToString(validation)
val validationDeserialized = Json.decodeFromString<Validation>(validationJson)
assertEquals(validation, validationDeserialized)
}
我想得到的输出(JSON示例):
{
"userName": "myUserName",
"validation": {"PasswordValidation": "WEAK"}
}
或(更接近标准)
{
"userName": "myUserName",
"validation": {
"type": "PasswordValidation",
"value": "WEAK"
}
}
半自定义或(如果需要)全自定义序列化程序是什么样子的?
谢谢你的帮助!
1条答案
按热度按时间y1aodyip1#
我也遇到了同样的问题,所以我使用了自定义序列化:
}