Сериализация неизменяемых объектов без конструктора в ObjectMapper
Пройдите тест, узнайте какой профессии подходите
Быстрый ответ
Jackson ObjectMapper дает возможность обработки неизменяемых объектов с помощью аннотаций @JsonCreator
и @JsonProperty
. Чтобы привязать поля JSON к параметрам конструктора, нужно пометить соответствующий конструктор или статический метод фабрики аннотацией @JsonCreator
, а каждый его аргумент – аннотацией @JsonProperty
.
Пример:
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Immutable {
private final String data;
@JsonCreator
public Immutable(@JsonProperty("data") String data) {
this.data = data;
}
// геттеры...
}
String json = "{\"data\":\"value\"}";
Immutable item = new ObjectMapper().readValue(json, Immutable.class);
Ключевые элементы:
@JsonCreator
: Позволяет инициализировать объекты без использования конструктора по умолчанию.@JsonProperty
: Связывает поля JSON с параметрами конструктора.
Особенности сериализации/десериализации
ParameterNamesModule, универсальный модуль Jackson
Применение ParameterNamesModule
упрощает работу с аннотациями и сокращает объем кода:
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new ParameterNamesModule());
Для Spring Boot ручная регистрация не требуется.
Круг спасения: DeserializationProblemHandler
Если нужно решить вопросы с десериализацией, и при этом изменить класс нельзя, воспользуйтесь DeserializationProblemHandler
:
ObjectMapper mapper = new ObjectMapper();
mapper.addHandler(new DeserializationProblemHandler() {
// Здесь реализация вашей логики обработки исключений.
});
Jackson и Java Records
Начиная с версии Jackson 2.12.0 и Java 16, сериализация и десериализация неизменяемых структур, описывемых с помощью Java records, стала ещё более удобной:
public record ImmutableRecord(String data) {}
ImmutableRecord record = mapper.readValue(json, ImmutableRecord.class);
Использование шаблона Builder для решения сложных задач
Шаблон Builder, или "построитель", поможет вам, если вам нужно больше контролировать процессы сериализации/десериализации:
class Immutable {
// Здесь определите класс Builder...
}
Этот шаблон поможет решить достаточно сложные задачи сериализации.
Обновленность версии библиотеки Jackson
Очень важно проверять, чтобы версия библиотеки Jackson поддерживала необходимые функциональные возможности.
Сохранение неизменяемости объектов
Использование публичного или защищённого конструктора по умолчанию может нарушить неизменяемость объекта, поэтому лучше его не использовать.
Использование одного ObjectMapper для всего приложения
С использованием подхода Singleton полезно работать с одним экземпляром ObjectMapper в приложении.
Управление ObjectMapper через Внедрение зависимостей
Использование Внедрения зависимостей для управления экземпляром ObjectMapper упрощает тестирование и обеспечивает большую модульность.
Визуализация
Представим, что десериализация неизменяемых объектов с помощью ObjectMapper аналогична процессу вскрытия запертого сундука:
У вас есть запертый сундук (неизменяемый объект), у которого нет замочной скважины (отсутствует конструктор по умолчанию):
+---------------+
| 🧰 (Заперт) |
| Где моя замочная скважина?! |
+---------------+
Чтобы открыть его, ObjectMapper'у понадобятся чертежи (@JsonCreator
), чтобы сделать ключ (@JsonProperty
):
Чертеж: @JsonCreator
Ключ: @JsonProperty => 🔐
При помощи этих инструментов ObjectMapper может открыть сундук:
+---------------+
| 🧰 (Открыт) |
+---------------+
И вот результат – успешно десериализованный неизменяемый объект:
Финальный результат: 📜✨ (Неизменяемые данные)
Задача выполнена! 🚀
Указания для архитекторов API
Ваша задача – разработать последовательный и интуитивно понятный дизайн API, который уменьшит путаницу и оптимизирует процесс сериализации.
Методы решения особых проблем десериализации
С помощью DeserializationContext
и JsonParser
можно эффективно управлять особыми проблемами, возникающими при десериализации.
Управление несколькими экземплярами ObjectMapper
Слишком большое количество экземпляров ObjectMapper может привести к беспорядку, который можно избежать, используя пул объектов.
Настраиваемые ObjectMapper'ы
Вы можете создавать экземпляры ObjectMapper на основе различных конфигураций с помощью фабричных методов.
Нюансы использования Java Records
Если вы используете Java records, учтите, что добавление геттеров с префиксами "get" или "is" может вызвать проблемы при сериализации.
Сохранение неизменяемости при обновлении
Важно сохранять неизменяемость объекта и целостность API, несмотря на обновления приложений и зависимостей.
Полезные материалы
- FasterXML/jackson-databind – Creator Annotations — детальное описание использования
@JsonCreator
для десериализации в Jackson на GitHub. - Использование Jackson ObjectMapper для работы с неизменяемыми объектами — обсуждение проблем и способов их решения при работе с неизменяемыми объектами и Jackson.
- Обработка JSON в Java с помощью API Jackson — подробное руководство по API Jackson.
- Десериализация неизменяемых классов без конструктора по умолчанию с помощью Jackson — обсуждение на Stack Overflow, которое объясняет особенности десериализации неизменяемых объектов.
- Десериализация Jackson с использованием шаблона Builder — руководство Baeldung по использованию шаблона Builder при десериализации Jackson.