@SerialInfo - Как управлять пользовательскими последовательными аннотациями с сериализацией Kotlinx? - PullRequest
0 голосов
/ 27 февраля 2020

Документация по сериализации Kotlinx

Согласно Kotlinx.serialization пользовательским аннотациям do c:

"Внутри процесса сериализации / десериализация, ваш собственный класс аннотаций доступен в SerialDescriptor объект ":

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

Что я хочу сделать

Мне нужно @Transient эквивалент, но условный:

  • classi c way, где: Json.stringify(serializer, myClass) работает как обычно.
  • пользовательский способ, где: Json.stringify(customSerializer, myClass) будет возвращать обычные json, но исключая все @MyAnnotation помеченные значения.

Вот мой код

@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. Где я могу получить доступ к ElementValueEncoder в пользовательском сериализаторе?

Я также нашел это пример демо в репозитории kotlinx.serialization github. Он использует TaggedEncoder & TaggedDecoder, где я могу переопределить encodeTaggedValue. Но и здесь я не знаю, как я могу использовать эти кодировщик / декодер в процессе сериализации / десериализации.

Наконец

Где я могу переопределить fun encodeElement(desc: SerialDescriptor, index: Int): Boolean и как я могу обработать мою собственную аннотацию сериализации?

Спасибо !!

1 Ответ

1 голос
/ 05 марта 2020

Прежде всего, вам нужно увеличить asp разницу между Сериализатором и Энкодером. Serializer (представлен KSerializer) определяет, как выглядит ваш класс, а Encoder (представлен, например, JsonOutput) определяет, как будут записываться данные. Вы можете найти больше информации об этой топике c здесь: https://github.com/Kotlin/KEEP/blob/master/proposals/extensions/serialization.md#core -api-Overview-and-mental-model .

Таким образом, функция пользовательских аннотаций в основном используется для обеспечения спецификация формата c информация для кодировщика. Типичное использование такой аннотации - ProtoId - идентификатор свойства, задающий c для формата protobuf, который должен распознаваться ProtobufEncoder. Такие аннотации обычно определяются авторами форматов вместе с их кодировщиками.

Здесь, как я вижу, вы хотите использовать уже существующий кодировщик (формат JSON), поэтому переопределение encodeElement невозможно поскольку Json кодировщики не могут быть разделены на подклассы. Я бы посоветовал вам использовать пользовательский json трансформирующий сериализатор для достижения вашей цели. К сожалению, в настоящее время kotlinx.serialization не имеет механизма для обобщения такого преобразования, поэтому вам нужно написать такой сериализатор для каждого класса.

...