@SerialInfo - 如何使用 Kotlinx 序列化管理用户定义的序列注释?

@SerialInfo - How to manage user-defined serial annotations with Kotlinx serialization?

Kotlinx 序列化文档

根据Kotlinx.serialization用户定义的注解doc

"Inside a process of serialization/deserialization, your own annotation class are available in SerialDescriptor object" :

override fun encodeElement(desc: SerialDescriptor, index: Int): Boolean {
    val annotations = desc.getElementAnnotations(index)
    ...
}

我想做什么

我需要一个 @Transient 等效项,但有条件:

这是我的代码

@SerialInfo
@Target(AnnotationTarget.PROPERTY)
annotation class CustomAnnotation

@Serializable
data class MyClass(val a: String, @CustomAnnotation val b: Int = -1)

我想构建一个自定义序列化器并实现类似

的东西
override fun encodeElement(desc: SerialDescriptor, index: Int): Boolean {
    val isTaggedAsCustomAnnotation = desc.getElementAnnotations(index).any{ it is CustomAnnotation }
    val myCondition = mySerializer.getMyConditionBlablabla

    if(myCondition && isTaggedAsCustomAnnotation) {
        encode()    
    }
    ...
}

我发现了什么

abstract class ElementValueEncoder : Encoder, CompositeEncoder {
    ...
    open fun encodeElement(desc: SerialDescriptor, index: Int): Boolean = true
}

但我不知道如何构建自定义序列化程序以便覆盖该函数 Encoder.encodeElement。我在哪里可以访问自定义 Serializer 中的 ElementValueEncoder?

我还在 kotlinx.serialization github 存储库中找到了这个 sample demo。它使用 TaggedEncoder & TaggedDecoder,我可以覆盖 encodeTaggedValue。但是我又一次不知道如何在 serialization/deserialization 的过程中使用那些 encoder/decoder。

终于

在哪里可以覆盖 fun encodeElement(desc: SerialDescriptor, index: Int): Boolean,以及如何处理我自己定义的序列化注释?

谢谢!!

首先,你需要掌握Serializer和Encoder的区别。 Serializer(由 KSerializer 表示)定义了您的 class 的样子,而 Encoder(由例如 JsonOutput 表示)定义了数据的记录方式。您可以在此处找到有关该主题的更多信息:https://github.com/Kotlin/KEEP/blob/master/proposals/extensions/serialization.md#core-api-overview-and-mental-model .

因此,自定义注释功能主要用于向编码器提供特定格式 信息。这种注释的典型用法是 ProtoId – 属性 id,特定于 protobuf 格式,应该被 ProtobufEncoder 识别。此类注释通常由格式作者与其编码器一起定义。

正如我所见,您在这里要做的是使用现有的编码器(JSON 格式),因此无法覆盖 encodeElement,因为 Json 编码器不能被 subclassed。我建议您使用 custom json transofrming serializer 来实现您的目标。不幸的是,目前 kotlinx.serialization 没有机制来概括这种转换,所以你需要为每个 class.

编写这样的序列化程序