繁体   English   中英

Jackson 从对象映射反序列化枚举

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM