Какие инструменты и библиотеки используются для сериализации и десериализации JSON в Java
Что проверяют
Знаете ли вы Jackson глубже, чем writeValueAsString, и понимаете ли, где в JSON-сериализации прячутся ошибки и уязвимости. Следом обычно спрашивают, как настроить маппер в Spring Boot или десериализовать полиморфный тип.
Как отвечать
Перечислите библиотеки с назначением:
- Jackson: стандарт де-факто, на нём работает Spring.
ObjectMapper, аннотации@JsonProperty,@JsonIgnore,@JsonCreator, поддержка records, деревоJsonNodeи потоковый APIJsonParser/JsonGeneratorдля больших файлов. В ветке 2.x дляjava.timeнужен модульjackson-datatype-jsr310. В Jackson 3 пакеты переехали вtools.jackson, а маппер стал неизменяемым и собирается черезJsonMapper.builder(); - Gson: простой и лёгкий, но в режиме поддержки. Работает через рефлексию полей и для Kotlin неудобен: игнорирует nullability и значения по умолчанию;
- Moshi: компактная альтернатива с нормальной поддержкой Kotlin и кодогенерацией адаптеров;
- JSON-B: спецификация Jakarta EE, пакет
jakarta.json.bind, эталонная реализация Yasson. Рядом JSON-P (jakarta.json) для дерева и потока; - kotlinx.serialization: для Kotlin, без рефлексии, сериализаторы генерирует плагин компилятора.
Детали, которые ждут от опытного кандидата. ObjectMapper потокобезопасен после настройки и создаётся один раз на приложение. FAIL_ON_UNKNOWN_PROPERTIES в чистом Jackson включён, и лишнее поле роняет десериализацию, а Spring Boot этот флаг выключает. Полиморфизм описывают через @JsonTypeInfo(use = JsonTypeInfo.Id.NAME) вместе с @JsonSubTypes.
Где спотыкаются
Создают new ObjectMapper() в каждом методе. Маппер кеширует сериализаторы, и пересоздание заметно бьёт по производительности.
Включают глобальную типизацию через устаревший enableDefaultTyping или Id.CLASS на полях типа Object. Имя класса из JSON открывает путь к десериализации «гаджетов» и удалённому выполнению кода. Безопаснее логические имена типов или PolymorphicTypeValidator.
Не фиксируют формат дат. Jackson 2.x по умолчанию пишет java.util.Date числом миллисекунд, а LocalDateTime без модуля не сериализует вовсе и бросает исключение.