我有一个简单的枚举我想序列化和反序列化。该课程如下:
public enum TipusViatge {
OCI,
NEGOCIS,
FAMILIA;
@Override
public String toString() {
return name().toUpperCase();
}
}
问题是,我通过一个宁静的呼叫发送它,接收方可以接收任何类型(所以它只知道它将接收对象)。所以杰克逊应该能够找出反序列化的论证类型。
有可能这样做吗?我当时认为在生成的json中包含类名应该允许Jackson弄清楚类型,但我一直无法这样做。
答案 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.使用我的客户序列化程序(
should use `getId()` instead of `name()`).
if (enumId != null) {
generator.writeString(enumId.getId());
}
中添加新模块
@JsonCreator
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将在所有情况下使用它。我认为这就是这个话题。我给你一个代码示例,使其更清晰(最好先编写一次,然后再解释两次):
decimate()