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

Posted

技术标签:

【中文标题】@SerialInfo - 如何使用 Kotlinx 序列化管理用户定义的串行注释?【英文标题】:@SerialInfo - How to manage user-defined serial annotations with Kotlinx serialization? 【发布时间】:2020-06-11 17:35:07 【问题描述】:

Kotlinx 序列化文档

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

“在一个序列化/反序列化的过程中,你自己的注解类SerialDescriptor对象中可用”

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

我想做什么

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

经典方式: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 存储库中找到了这个 sample demo。它使用TaggedEncoderTaggedDecoder 我可以覆盖encodeTaggedValue。但是在这里我不知道如何在序列化/反序列化过程中使用这些编码器/解码器。

终于

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

谢谢!!

【问题讨论】:

【参考方案1】:

首先要掌握Serializer和Encoder的区别。序列化器(由KSerializer 表示)定义您的类的外观,编码器(由例如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 编码器进行子类化。我建议您使用custom json transofrming serializer 来实现您的目标。不幸的是,目前 kotlinx.serialization 没有机制来泛化这种转换,因此您需要为每个类编写这样的序列化器。

【讨论】:

以上是关于@SerialInfo - 如何使用 Kotlinx 序列化管理用户定义的串行注释?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 kotlin 中使用片段

如何在 Kotlin 中使用 ViewModelProviders

如何在Kotlin中使用Gradle构建缓存?

如何在 Kotlin Multiplatform(纯 kotlin)中进行延迟

如何使用Kotlin进行Android开发

如何在 Kotlin/Multiplatform 项目中使用 .klib 库