Десериализуйте перечисление как из целого числа, так и из строки в Java

#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;  } }  
  1. Перечисление не может быть «из коробки» сериализовано из целого числа, так как оно не начинается с 0 ( index value outside legal index range исключение получения).
  2. Сегодня у нас уже есть поток, который получает строку (например, «АКТИВНЫЙ») и успешно десериализует ее. Я не хочу изменять/вредить этой способности.

Я попытался добавить @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; }  

Это в основном принимает значение любого типа, проверяет, что это такое, и соответственно разрешает значение перечисления.