[英]Jackson deserialise enum from a map of objects
因此,假设我们有一个带有Map<String, Object>
的 Pojo,我们如何告诉 Jackson objectmapper 某些键名实际上是枚举而不是字符串? 例如,映射将不相等,因为 attr5 将被反序列化为 String 而不是 MyEnum。
public class App {
enum MyEnum {
A,
B,
C;
}
static class Pojo {
private Map<String, Object> map = new HashMap<>();
public void setEntry(String key, Object value) {
map.put(key, value);
}
public Map<String, Object> getMap() {
return map;
}
public void setMap(Map<String, Object> map) {
this.map = map;
}
}
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
Pojo pojo = new Pojo();
pojo.setEntry("attr1", 1);
pojo.setEntry("attr2", false);
pojo.setEntry("attr3", "hello");
pojo.setEntry("attr4", Arrays.asList("a", "b", "c"));
pojo.setEntry("attr5", MyEnum.A);
String pojoString = mapper.writeValueAsString(pojo);
Pojo newPojo = mapper.readValue(pojoString, Pojo.class);
System.out.println("Maps are equal: " + newPojo.getMap().equals(pojo.getMap()));
}
}
正如 fps 所说,jackson 无法区分枚举和 Object 中的 String。 在这种情况下,我会建议您在 json 中传输变量的类型。 它非常简单,可以满足您的需求。 请尝试 :
杰克逊配置:
ObjectMapper mapper = new ObjectMapper();
PolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator
.builder()
.allowIfBaseType(Object.class)
.build();
mapper.activateDefaultTyping(ptv, ObjectMapper.DefaultTyping.JAVA_LANG_OBJECT);
您的 json 将如下所示:
{"map":{"attr5":["com.company.MyEnum","A"],"attr2":false,"attr1":1,"attr4":["java.util.Arrays$ArrayList",["a","b","c"]],"attr3":"hello"}}
它只会将类型信息添加到带有对象类型的 Map 中的值。 您的测试将通过,因为两个地图将相等。
我的解决方案是为地图制作自定义序列化程序。
class CustomMapDeserializer extends StdDeserializer<Map<String,Object>> {
public CustomMapDeserializer() {
this(null);
}
public CustomMapDeserializer(Class<?> vc) {
super(vc);
}
@Override
public Map<String,Object> deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
Map<String,Object> res = new LinkedHashMap<>();
for(Map.Entry<String, JsonNode> n : jp.getCodec().readTree(jp).fields()){
if(!n.getKey().equals("attr5")) //Only attr5 will be taken as enum
res.put(n.getKey(),mapper.treeToValue(n.getValue(),Object.class))
else
res.put(n.getKey(),mapper.treeToValue(n.getValue(),MyEnum.class))
}
return res;
}
}
class Pojo {
@JsonDeserialize(using= CustomMapDeserializer.class) //Apply Deserializer here
private Map<String, Object> map = new HashMap<>();
public void setEntry(String key, Object value) {
map.put(key, value);
}
public Map<String, Object> getMap() {
return map;
}
public void setMap(Map<String, Object> map) {
this.map = map;
}
}
...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.