使用Jackson对带有整数键的映射进行反序列化

Ale*_*exR 5 java jackson fasterxml json-deserialization

我必须将一个简单的整数到字符串映射序列化为JSON,然后将其读回.序列化非常简单,但由于JSON键必须是字符串,因此生成的JSON如下所示:

{
  "123" : "hello",
  "456" : "bye",
}
Run Code Online (Sandbox Code Playgroud)

当我使用以下代码阅读它时:

new ObjectMapper().readValue(json, Map.class)
Run Code Online (Sandbox Code Playgroud)

我得到的Map<String, String>不是Map<Integer, String>我需要的.

我尝试添加密钥反序列化器如下:

    Map<Integer, String> map1 = new HashMap<>();
    map1.put(1, "foo");
    map1.put(2, "bar");


    ObjectMapper mapper = new ObjectMapper();
    SimpleModule module = new SimpleModule();
    module.addKeyDeserializer(Integer.class, new KeyDeserializer() {
        @Override
        public Object deserializeKey(String key, DeserializationContext ctxt) throws IOException, JsonProcessingException {
            System.out.println("deserialize " + key);
            return Integer.parseInt(key);
        }
    });

    mapper.registerModule(module);
    String json = mapper.writeValueAsString(map1);


    Map map2 = mapper.readValue(json, Map.class);
    System.out.println(map2);
    System.out.println(map2.keySet().iterator().next().getClass());
Run Code Online (Sandbox Code Playgroud)

不幸的是我的密钥deserialzier永远不会被调用,map2事实上Map<String, String>,所以我的例子打印:

{1=foo, 2=bar}
class java.lang.String
Run Code Online (Sandbox Code Playgroud)

我做错了什么以及如何解决问题?

Wan*_*ker 10

使用

Map<Integer, String> map2 = 
        mapper.readValue(json, new TypeReference<Map<Integer, String>>(){});
Run Code Online (Sandbox Code Playgroud)

要么

    Map<Integer, String> map2 = 
        mapper.readValue(json, TypeFactory.defaultInstance()
                         .constructMapType(HashMap.class, Integer.class, String.class));
Run Code Online (Sandbox Code Playgroud)

您的程序将输出以下文字:

deserialize 1
deserialize 2
{1=foo, 2=bar}
class java.lang.Integer
Run Code Online (Sandbox Code Playgroud)

  • 杰克逊不知道地图的键和值的类型.需要告诉它.如果您要反序列化到POJO,并且POJO有一个Map <Integer,String>,那么,Jackson似乎知道该怎么做.但是,在直接解析Map时,上面似乎是告知Jackson的方法 (3认同)