Решение проблемы десериализации enum в Java с Jackson
Пройдите тест, узнайте какой профессии подходите
Быстрый ответ
Для выполнения операций сериализации и десериализации перечислений (enum) в Jackson применяются аннотации @JsonValue
и @JsonCreator
. Аннотация @JsonValue
отмечает метод, возвращающий значение для сериализации, в то время как @JsonCreator
используется для статического метода, который восстанавливает перечисление из его сериализованной формы:
public enum Type {
YES("Y"), NO("N");
private final String code;
Type(String code) {
this.code = code;
}
@JsonValue
public String getCode() {
return code;
}
@JsonCreator
public static Type fromCode(String code) {
return Arrays.stream(Type.values())
.filter(type -> type.code.equals(code))
.findFirst()
.orElseThrow(() -> new IllegalStateException("Нераспознанный код: " + code));
}
}
Данный пример демонстрирует, что значение Type.YES
будет сериализовано как "Y"
и, в свою очередь, десериализовано из "Y"
в Type.YES
.
Регистр, проверка на ошибки и прочие особенности
При наличии нестандартных правил привязки перечислений или в случае, когда JSON не учитывает регистр, можно создать Map
для регистронезависимой десериализации.
public static Type forValue(String code) {
return stringToEnumMap.get(StringUtils.lowerCase(code));
}
Также стоит задуматься об обработке неожиданных значений в сериализаторе. Вы можете предусмотреть возврат null
из метода toValue()
или выброс исключения.
Пользовательские сериализаторы/десериализаторы: делайте по-своему!
Для более точного контроля над процессами сериализации и десериализации вы можете использовать свои собственные классы сериализаторов и десериализаторов. Это позволяет реализовывать более сложную логику и обеспечивает гибкость при работе с нестандартными формами перечислений.
public class MySerializer extends StdSerializer<MyEnum> {
public MySerializer() {
super(MyEnum.class);
}
@Override
public void serialize(MyEnum value, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeString(value.getCustomString());
}
}
С версии Jackson 2.6 можно использовать аннотацию @JsonProperty
для определения имени каждого значения перечисления при сериализации.
public enum Role {
@JsonProperty("Admin")
ADMINISTRATOR,
@JsonProperty("Janitor")
SUPER_USER
}
Крайние случаи: возвращение Enum!
При работе с перечислениями, имеющими дополнительные характеристики, или когда необходима полиморфная десериализация, настройте ваши решения таким образом, чтобы Jackson мог корректно их обработать.
Для обработки неопределённых или устаревших значений перечислений можно использовать аннотацию @JsonEnumDefaultValue
.
Визуализация
Работа с сериализацией/десериализацией перечислений в Jackson напоминает работу с конструктором LEGO:
Блок (🟨 Enum)
- Блок A (🟥 Индикатор)
- Блок B (🟩 Основное содержание)
- Блок C (🟦 Завершение)
Сериализация аналогична разбиранию конструктора:
@JsonValue
public String toJson() {
return name().toLowerCase(Locale.ROOT);
}
После этого 🟦 преобразуется в JSON в виде "завершение"
.
Десериализация — это сборка конструктора обратно:
@JsonCreator
public static Dish fromJson(String jsonValue) {
return Dish.valueOf(jsonValue.toUpperCase(Locale.ROOT));
}
Таким образом, "завершение"
вновь становится 🟦.
К размышлению: хорошее, плохое и ужасное
Настройка ObjectMapper
Настройте ObjectMapper
, чтобы глобально управлять обработкой перечислений в вашем приложении.
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
Логика десериализации
Логика десериализации должна быть готова к эффективной работе с разнообразными данными, обеспечивая таким образом надёжность всего приложения.
Правильная работа!
Убедитесь, что ваши сериализаторы/десериализаторы совместимы с используемыми версиями Java и Jackson.
Полезные материалы
- JsonEnumDefaultValue (Jackson-annotations 2.9.0 API)
- Serialization features · FasterXML/jackson-databind Wiki · GitHub
- JacksonPolymorphicDeserialization · FasterXML/jackson-docs Wiki · GitHub
- No serializer found for class org.hibernate.proxy.pojo.javassist.Javassist? – Stack Overflow
- Jackson Custom Serializer – Составление собственного сериализатора
- Jackson Custom Deserializer – Реализация собственной десериализации
- Jackson Advanced Polymorphic Type Handling