Json
Модуль Json позволяет создавать производительные и без использования рефлексии читатели и писатели для классов приложения посредствам разметки классов аннотациями.
Подключение¶
Зависимость build.gradle:
Модуль:
Зависимость build.gradle.kts:
Модуль:
Запись¶
Можно воспользоваться @JsonWriter для создания только писателя:
Чтение¶
Можно воспользоваться @JsonReader для создания только читателя:
Чтение & Запись¶
Можно воспользоваться @Json для создания сразу читателя и писателя.
В большинстве случаев предпочтительнее использовать именно аннотацию @Json:
Обязательные поля¶
По умолчанию все поля объявленные в объекте считаются обязательными (NotNull).
По умолчанию все поля объявленные в объекте которые не используют Kotlin Nullability синтаксис считаются обязательными (NotNull).
Необязательное поля¶
В случае если поле в Json является необязательным, то есть может отсутствовать то,
можно использовать аннотацию @Nullable для соответствия поля в Json и DTO:
- Подойдет любая аннотация
@Nullable, такие какjavax.annotation.Nullable/jakarta.annotation.Nullable/org.jetbrains.annotations.Nullable/ и т.д.
Предполагается использовать Kotlin Nullability синтаксис и помечать такой параметр как Nullable:
Именование поля¶
В случае если поле в Json называется иначе от того что требуется использовать в классе,
можно использовать аннотацию @JsonField для соответствия поля в Json и DTO.
Игнорирование поля¶
В случае если поле в DTO не хочется читать/писать,
можно использовать аннотацию @JsonSkip и проигнорировать такое поле.
Уровни записи¶
Поведение по умолчанию не подразумевает запись полей с null значениями. (1)
IncludeType.NON_NULL- включать поле в запись если неnull
В случае если хочется изменить поведение записи в этих моментах то предлагается использовать аннотацию @JsonInclude.
Аннотацию можно использовать не только над полем, но также над классом и тогда правило будет действовать на все поля сразу.
Доступны различные варианты использования:
IncludeType.ALWAYS- включать поле в запись всегдаIncludeType.NON_NULL- включать поле в запись если неnullIncludeType.NON_EMPTY- включать поле в запись если это неnullи не пустая коллекция
Пример использования аннотации:
Указание конструктора¶
В случае если хочется использовать определенный конструктор для сериализации,
то это можно сделать с указанием над конструктором аннотации @JsonReader либо аннотации которая имеет меньший приоритет @Json:
JsonNullable обертка¶
В случае если во время десериализации, хочется отличать отсутствующее поле от указанного null значения,
предполагается использовать специальный тип JsonNullable, который позволяет отражать все состояния поля после десериализации.
Изолированные классы и интерфейсы¶
В случае если требуется писать различные Json объекты в зависимости от значения в конкретном поле, предполагается использовать изолированный класс/интерфейс для представления таких объектов.
Для поддержки изолированных классов добавлены две аннотации:
@JsonDiscriminatorField- указывает поле дискриминатора в DTO, которым помечается sealed класс/интерфейс@JsonDiscriminatorValue- значение для вышеуказанного поля, помечает класс-наследник sealed класса/интерфейса
@Json
@JsonDiscriminatorField("type")
public sealed interface Event {
@JsonDiscriminatorValue("firstType")
record FirstTypeEvent(String id, String type) implements Event {}
@JsonDiscriminatorValue("secondType")
record SecondTypeEvent(String id, Integer code) implements Event {}
@JsonDiscriminatorValue("thirdType")
record ThirdTypeEvent(String id, Boolean status) implements Event {}
}
@Json
@JsonDiscriminatorField("type")
sealed interface Event {
@JsonDiscriminatorValue("firstType")
data class FirstTypeEvent(val id: String, val type: String) : Event
@JsonDiscriminatorValue("secondType")
data class SecondTypeEvent(val id: String, val code: Integer) : Event
@JsonDiscriminatorValue("thirdType")
data class ThirdTypeEvent(val id: String, val status: Boolean) : Event
}
Для классов-наследников будут созданы JsonReader и JsonWriter по тем же правилам, как если бы на них была аннотация @Json и создастся JsonReader и JsonWriter для самого sealed класса/интерфейса.
Json объект ниже будет записан в класс FirstTypeEvent:
Поддерживаемые типы¶
Модуль предоставляет обширный список поддерживаемых из коробки типов которые покрывают большую часть того что может понадобиться.
Список поддерживаемых типов
- Boolean
- boolean
- Short
- short
- Integer
- int
- Long
- long
- Double
- double
- Float
- float
- byte[]
- String
- UUID
- BigInteger
- BigDecimal
- List
- Set
- LocalDate
- LocalTime
- LocalDateTime
- OffsetTime
- OffsetDateTime
- ZonedDateTime
- Year
- YearMonth
- MonthDay
- Month
- DayOfWeek
- ZoneId
- Duration
Собственные типы¶
В случае если требуется писать/читать собственный тип, то предлагается зарегистрировать собственную фабрику для JsonReader / JsonWriter:
Пример регистрации собственно JsonWriter:
Jackson¶
В случае если хочется использовать Jackson для записи/чтения, то можно самому зарегистрировать фабрику
предоставляющую ObjectMapper и соответствующие Mappers которые требуются в других Kora модулях будут предоставлены зависимостью ниже:
Зависимость build.gradle:
annotationProcessor "ru.tinkoff.kora:json-annotation-processor"
implementation "ru.tinkoff.kora:jackson-module"
Модуль:
Зависимость build.gradle.kts:
Модуль: