包含枚举类型以使用jackson序列化和反序列化

时间:2017-09-10 08:40:22

标签: java rest enums jackson

我有一个简单的枚举我想序列化和反序列化。该课程如下:

    public enum TipusViatge {
    OCI,
    NEGOCIS,
    FAMILIA;

    @Override
    public String toString() {
        return name().toUpperCase();
    }
}

问题是,我通过一个宁静的呼叫发送它,接收方可以接收任何类型(所以它只知道它将接收对象)。所以杰克逊应该能够找出反序列化的论证类型。

有可能这样做吗?我当时认为在生成的json中包含类名应该允许Jackson弄清楚类型,但我一直无法这样做。

1 个答案:

答案 0 :(得分:0)

我已经解决了这个问题了一段时间。

第一您可以使用Map<String, Object>反序列化您的json。它总是起作用;你得到标准类型(你的枚举将被称为普通字符串)。

第二在一般情况下,您总是知道您阅读的是哪种对象。这是顶级对象,您可以将其设置为Jackson mapper:mapper.readerFor(cls).readValue(json)。如果您的枚举是此cls对象的一部分,那么Jackson知道类型并只读取值并解析它。

3rd 你实际上可以有一个json字符串的多个对象。我在谈论继承。你可以在Jackson文档中查看@JsonTypeInfo

第4次想象你读了一个json源而且不知道你读了什么。在这种情况下,您可以让杰克逊在对象的开头写下标记。就像你询问类名一样。我认为这与@JsonRootName有关。您可以在此处查看:Jackson JSON Deserialization with Root Element

我认为现在如何处理杰克逊的物品很干净。我的意思是我们知道如何告诉杰克逊我们想要反序列化的元素。现在我们有一个问题:如何序列化json - &gt;我们的枚举。

第5次这不是问题,开箱即用。 Jackson使用name()方法序列化枚举,并valueOf()进行反序列化。你可以在杰克逊的EnumDeserializer附近看一下。

6th 我不喜欢这种行为,因为它是个案敏感的。我遇到的情况是,当人们手动编写json字符串时,使用小写并且不能反序列化它。而且,我相信,将枚举常量直接写入json文件是一种不好的做法,因为如果我想重构枚举的名称,那么所有已存在的json字符串也应该被修改为(brrr)。为了解决这些问题,我做了以下技巧: 1.使用parseId(String id)实现具有getId()的默认实现的EnumId接口,使用getId()来标识枚举常量并使用ignore case进行比较。 1.我在枚举中添加了id字段 2.添加parseId(String id) - 以进行序列化 3.添加ObjectMapper - 进行反序列化 4.使用我的客户序列化程序(

)在Jackson should use `getId()` instead of `name()`). if (enumId != null) { generator.writeString(enumId.getId()); } 中添加新模块
@JsonCreator
  1. 告诉杰克逊如何反序化这个枚举。这是一个很难的情况,因为在不同的来源,杰克逊使用不同的deseriaization层次结构,只是添加另一个模块到ObjectMapper与自定义反序列化(就像在4。)将不适用于所有情况。为了解决这个问题,我发现我们可以在枚举中将public interface EnumId { String name(); default String getId() { return name().toLowerCase(); } static <T extends Enum<?> & EnumId> T parseId(Class<T> cls, String id) { T res = parseId(cls.getEnumConstants(), id, null); if (res != null) { return res; } throw new EnumConstantNotPresentException(cls, id); } static <T extends EnumId> T parseId(T[] values, String id, T def) { for (T value : values) { if (id != null ? id.equalsIgnoreCase(value.getId()) : value.getId() == null) { return value; } } return def; } static <T extends EnumId> T get(T value, T def) { return value != null ? value : def; } } public enum TipusViatge implements EnumId { OCI, NEGOCIS, FAMILIA; @JsonCreator public static TipusViatge parseId(String id) { return EnumId.parseId(TipusViatge.class, id); } } 添加到parseId(String id)方法中,Jackson将在所有情况下使用它。
  2. 我认为这就是这个话题。我给你一个代码示例,使其更清晰(最好先编写一次,然后再解释两次):

    decimate()