1

Kotlinx 序列化文档

根据Kotlinx.serialization用户定义的注释文档

“在序列化/反序列化过程中,您自己的注释类SerialDescriptor对象中可用”

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

我想做的事

我需要一个@Transient等价的,但有条件的:

  • 经典方式 where :Json.stringify(serializer, myClass)照常工作。
  • 自定义方式 where :Json.stringify(customSerializer, myClass)将返回通常的 json 但排除所有@MyAnnotation-tagged 值。

这是我的代码

@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 repo 中找到了这个示例演示。它使用TaggedEncoder&TaggedDecoder我可以覆盖的地方encodeTaggedValue。但是在这里我不知道如何在序列化/反序列化过程中使用这些编码器/解码器。

最后

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

谢谢 !!

4

1 回答 1

1

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

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

如我所见,您在这里想要做的是使用已经存在的编码器(JSON 格式),因此encodeElement无法覆盖,因为无法对 Json 编码器进行子类化。我建议您使用自定义 json 转换序列化程序来实现您的目标。不幸的是,目前 kotlinx.serialization 没有泛化这种转换的机制,因此您需要为每个类编写这样的序列化程序。

于 2020-03-05T11:30:31.873 回答