java如何在嵌套映射中使用Jackson KeyDeserializer?
问题
在现有的应用程序中,我必须反序列化可能的深度嵌套映射,并在所有级别的所有键上应用自定义Jackson反序列化程序
由于应用程序动态处理各种数据模型,我无法使用带有明确类型映射的显式数据模型。。。相反,我使用Map<String, Object>
并检查反序列化的Object
值本身是否为Map
这会导致自定义反序列化程序仅应用于顶级映射
更新:需要注意的是,我无法将反序列化程序绑定到所有映射,因为我的数据模型通常也有更具体的映射。对于开放式JSON设置,我通常有一个通用的Map<String, Object>
字段;与例如Map<EnumType, Double>
一起生活以获得更明确的配置位
范例
为了举例说明,我提出了以下玩具示例:
ObjectMapper objectMapper = new ObjectMapper().registerModule(new SimpleModule()
.addKeyDeserializer(String.class, new KeyDeserializer() {
@Override
public Object deserializeKey(String s, DeserializationContext deserializationContext) {
return s.toUpperCase();
}
}));
Map<String, Object> value = objectMapper.readValue(
"{\"zero\": 1, \"two\": { \"three\": 4 }}",
new TypeReference<Map<String, Object>>() {}
);
assertThat(value).containsKeys("ZERO", "TWO"); // pass
assertThat((Map) value.get("TWO")).containsKey("THREE"); // fail
最后一行代码失败:
java.lang.AssertionError: Expecting: <{"three"=4}> to contain key: <"THREE">
我无法将类型声明为Map<String, Map<String, Object>>
,因为int值处于同一级别。如果我尝试,我会得到:
Cannot deserialize instance of
java.util.LinkedHashMap
out of VALUE_NUMBER_INT token
问题
在本例中,即使需要将所有嵌套映射声明为Object
,但在所有嵌套映射中获取大写键的最佳方法是什么
有没有其他方法来解决这个问题
# 1 楼答案
下面是一个有效的解决方案。虽然它没有使用KeyDeserializer,但正如您所发现的,KeyDeserializer不会深入到JSON中,将所有内部JSON字段名都大写
下面的解决方案使用JsonDeserializer而不是KeyDeserializer。我以您的示例为例,通过一个更复杂的JSON来测试它。它遍历JSON中的所有对象,以及它遇到的所有字段名的大写字母
下面是它产生的输出
代码假定最外层的JSON对象是一个映射。因此,需要在JsonDeserializer中进行少量更新,以将数组或标量作为最外层的JSON进行处理