#java #enums #jackson #deserialization
Вопрос:
Я добавляю новую логику кода, используя события CDC (изменение данных захвата). status
Поле, поступающее из базы данных, представлено в виде int и должно быть десериализовано в перечисление. Это перечисление:
public enum Status { ACTIVE(21), CANCELLED(22), EXPIRED(23), FAILED(24), PAUSED(25); private static final Maplt;Integer, Statusgt; map = new HashMaplt;gt;(); static { for (val value : Status.values()) { if (map.put(value.getId(), value) != null) { throw new IllegalArgumentException("duplicate id: " value.getId()); } } } public static Status getById(Integer id) { return map.get(id); } private Integer id; Status(Integer id) { this.id = id; } public Integer getId() { return id; } }
- Перечисление не может быть «из коробки» сериализовано из целого числа, так как оно не начинается с 0 (
index value outside legal index range
исключение получения). - Сегодня у нас уже есть поток, который получает строку (например, «АКТИВНЫЙ») и успешно десериализует ее. Я не хочу изменять/вредить этой способности.
Я попытался добавить @JsonCreator
здесь:
@JsonCreator public static SubscriptionStatus getById(Integer id) { return map.get(id); }
Но теперь десериализовать строку больше невозможно. Я предпочитаю иметь простое решение, а не создавать для него пользовательский десериализатор (я предполагаю, что он должен быть).
Комментарии:
1. Вы пробовали использовать
Object
и проверяли, получаете ли выString
илиNumber
/Integer
?2. Он десериализуется в целое число, но я все еще не уверен, что мне с ним делать?
3. Ну, если это целое число, вам нужно рассматривать его как идентификатор и выполнять соответствующий поиск. Если бы вы получили строку, вы могли бы предположить, что это имя (возможно, вы захотите проверить, может ли это быть идентификатор, закодированный в виде целого числа).
Ответ №1:
Попробуйте что-нибудь вроде этого:
@JsonCreator public static Status get(Object reference) { if( reference instanceof Number num) { return getById(num.intValue()); } else if( reference instanceof String str) { //the string might contain the id as well, e.g. "21" for ACTIVE //so you might want to check the string for this, if this is expected return Enum.valueOf(Status.class, str); } return null; }
Это в основном принимает значение любого типа, проверяет, что это такое, и соответственно разрешает значение перечисления.