1. 概述
本文我们将进一步学习 Jackson 的高级用法 - 如何处理Map中的Null Value或Null Key。
2. 忽略Map中的所有Null值
在 Jackson 中我们通过设置 ObjectMapper 全局控制null值序列化行为:
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(Include.NON_NULL);
下面示例中,值为null的元素不会被序列化,即结果中不会包含 dtoObject2
字段:
@Test
public void givenIgnoringNullValuesInMap_whenWritingMapObjectWithNullValue_thenIgnored()
throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(Include.NON_NULL);
MyDto dtoObject1 = new MyDto();
Map<String, MyDto> dtoMap = new HashMap<String, MyDto>();
dtoMap.put("dtoObject1", dtoObject1);
dtoMap.put("dtoObject2", null);
String dtoMapAsString = mapper.writeValueAsString(dtoMap);
assertThat(dtoMapAsString, containsString("dtoObject1"));
assertThat(dtoMapAsString, not(containsString("dtoObject2")));
}
3. Map 序列化键名为Null的字段
默认情况下,Jackson 不允许序列化key为null的Map,会抛出下面的异常:
c.f.j.c.JsonGenerationException:
Null key for a Map not allowed in JSON (use a converting NullKeySerializer?)
at c.f.j.d.s.i.FailingSerializer.serialize(FailingSerializer.java:36)
当然,Jackson非常灵活,为了解决这一问题,我们可以自定义一个 null key serializer 重写默认的序列化行为:
class MyDtoNullKeySerializer extends StdSerializer<Object> {
public MyDtoNullKeySerializer() {
this(null);
}
public MyDtoNullKeySerializer(Class<Object> t) {
super(t);
}
@Override
public void serialize(Object nullKey, JsonGenerator jsonGenerator, SerializerProvider unused)
throws IOException, JsonProcessingException {
jsonGenerator.writeFieldName("");
}
}
该实现中我们用空字符串替换null key。
测试用例:
@Test
public void givenAllowingMapObjectWithNullKey_whenWriting_thenCorrect()
throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
mapper.getSerializerProvider().setNullKeySerializer(new MyDtoNullKeySerializer());
MyDto dtoObject = new MyDto();
dtoObject.setStringValue("dtoObjectString");
Map<String, MyDto> dtoMap = new HashMap<String, MyDto>();
dtoMap.put(null, dtoObject);
String dtoMapAsString = mapper.writeValueAsString(dtoMap);
assertThat(dtoMapAsString, containsString("\"\""));
assertThat(dtoMapAsString, containsString("dtoObjectString"));
}
4. 忽略 Null 字段
除了Map, Jackson 提供了很多配置和方法处理 null 字段,感兴趣的朋友可以参考这篇教程
5. 总结
Map序列化很常见,Jackson 为此提供了很多配置方法,方便我们能更好的控制输出结果。
它同样提供了许多方法来处理Collection类型的数据。
最后,本文示例中的所有源码,可以在[GitHub](https://github.com/eugenp/tutorials/tree/master/jackson-modules/jackson-conversions#readme "Github Project covering all Jackson examples)上找到。