According to Kotlinx.serialization
user-defined annotations 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)
...
}
I need a @Transient
equivalent, but conditional:
Json.stringify(serializer, myClass)
works as usual. Json.stringify(customSerializer, myClass)
would return usual json but exculding all @MyAnnotation
-tagged values.Here is my code
@SerialInfo
@Target(AnnotationTarget.PROPERTY)
annotation class CustomAnnotation
@Serializable
data class MyClass(val a: String, @CustomAnnotation val b: Int = -1)
And I would like to build a custom Serializer and achieve something like
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
}
But I don't know how I can build a custom Serializer so that I can override that function Encoder.encodeElement
. Where can I access to ElementValueEncoder in a custom Serializer ?
I also found this sample demo in kotlinx.serialization github repo. It's using TaggedEncoder
& TaggedDecoder
where I'm able to override encodeTaggedValue
. But here again I don't know how I can use those encoder/decoder in a process of serialization/deserialization.
Where can I override fun encodeElement(desc: SerialDescriptor, index: Int): Boolean
, and how I can handle my own-defined serialization annotation ?
Thanks !!
First of all, you need to grasp the difference between Serializer and Encoder. Serializer (represented by KSerializer
) defines how your class looks like, and Encoder (represented by e.g. JsonOutput
) defines how data will be recorded. You can find more info on that topic here: https://github.com/Kotlin/KEEP/blob/master/proposals/extensions/serialization.md#core-api-overview-and-mental-model .
So, custom annotations feature is mainly used for providing format-specific information to Encoder. Typical usage of such an annotation is ProtoId
– property id, specific to protobuf format, that should be recognized by ProtobufEncoder
. Such annotations are usually defined by format authors alongside their encoders.
What you want to do here, as I can see, is to use already existing encoder (JSON format), so overriding encodeElement
is impossible since Json encoders can not be subclassed. I'd advise you to use custom json transofrming serializer to achieve your goal. Unfortunately, currently kotlinx.serialization does not have mechanism to generalize such a transformation, so you need to write such serializer for each class.