【问题标题】:Deserialize enum from both Integer and String in Java从 Java 中的 Integer 和 String 反序列化枚举
【发布时间】:2022-01-14 03:06:01
【问题描述】:

我正在添加一个新的代码逻辑,使用 CDC(捕获数据更改)事件。 来自 DB 的 status 字段表示为 int,应反序列化为枚举。 这是枚举:

public enum Status {

    ACTIVE(21),
    CANCELLED(22),
    EXPIRED(23),
    FAILED(24),
    PAUSED(25);

    private static final Map<Integer, Status> map = new HashMap<>();

    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. 枚举不能“开箱即用”从 Integer 序列化,因为它 不是从 0 开始(收到 index value outside legal index range 异常)。
  2. 今天我们已经有一个接收字符串(例如“ACTIVE”)并成功反序列化的流。我不想更改/损害此功能。

我已尝试在此处添加@JsonCreator

@JsonCreator
public static SubscriptionStatus getById(Integer id) {
    return map.get(id);
}

但是现在不可能再反序列化 String 了。我更喜欢有一个简单的解决方案,而不是为它创建一个自定义的反序列化器(我认为应该有一个)。

【问题讨论】:

  • 您是否尝试使用Object 并检查您得到的是String 还是Number/Integer
  • 它被反序列化为一个Integer,但我仍然不确定我应该如何处理它?
  • 好吧,如果它是一个整数,您需要将其视为 id 并相应地进行查找。如果你得到一个字符串,你可以假设它是名称(你可能想检查它是否是编码为整数的 id)。

标签: java enums jackson deserialization


【解决方案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;
}

这基本上接受任何类型的值,检查它是什么并相应地解析枚举值。

【讨论】:

    猜你喜欢
    • 2013-09-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-29
    • 1970-01-01
    相关资源
    最近更新 更多