记一次Jackson引发的血案

记一次Jackson引发的血案

昨天修改项目,想用Jackson逐渐替换项目中使用的Fastjson,项目较旧,已经配置了FastJsonHttpMessageConverter用于springmvc的返回值序列化,这是前提。

既然是用了Jackson解析json,有几个接口返回值里里有JsonNode类型,这是jackson的类,FastJson无法序列化,所以配置文件里添加了MappingJackson2HttpMessageConverter替代FastJsonHttpMessageConverter

替换过后能序列化JsonNode了,但ios设备闪退…

到公司检查逻辑,默认情况下的MappingJackson2HttpMessageConverter会将值为null的数据序列化成null,而FastJson的会删除null值。

1
2
3
4
5
6
7
8
9
10
//fastJson的返回值,b被删除了
{
"a":"a"
}

//Jackson的返回值
{
"a":"a"
"b":null
}

看上面的对比,若b为null的情况下,均在默认情况下,FastJson会删除该键值对,Jackson会序列化成"b":null

估计是iso用的反序列化工具不支持值为null的情况导致的闪退。安卓的不会有问题。

在配置文件里定制MappingJackson2HttpMessageConverter,让其忽略值为null的数据,解决问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<bean id="jacksonHttpMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="com.fasterxml.jackson.databind.ObjectMapper">
<!--值为null时不返回-->
<property name="serializationInclusion">
<util:constant static-field="com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL"/>
</property>
<!--返回时间格式-->
<property name="dateFormat">
<bean class="java.text.SimpleDateFormat">
<constructor-arg value="yyyy-MM-dd HH:mm:ss"/>
</bean>
</property>
</bean>
</property>
</bean>

代码可以这么写

1
2
3
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

JsonNode里面的NullNode因为不属于null,所以仍然会序列化成null,简单点的办法就是序列化之前遍历移出。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
private static void removeNullNode(JsonNode nodes) {
if (nodes.isArray()) {
Iterator<JsonNode> iterator = nodes.iterator();
while (iterator.hasNext()) {
JsonNode next = iterator.next();
if (next.isNull()) {
iterator.remove();
} else {
removeNullNode(next);
}
}
} else if (nodes.isObject()) {
ObjectNode os = (ObjectNode) nodes;
Iterator<Map.Entry<String, JsonNode>> fields = os.fields();
while (fields.hasNext()) {
Map.Entry<String, JsonNode> next = fields.next();
if (next.getValue().isNull()) {
fields.remove();
} else {
removeNullNode(next.getValue());
}
}
}
}

2020-05-08更新:

​ 有一个小坑,如果发现返回值对象中的字段为null能屏蔽,返回map内value为null不能屏蔽,请考虑下升级jackson版本,高版本能解决这个问题。

​ 我用的2.10.1可以屏蔽map中的null值。


记一次Jackson引发的血案
https://www.huangchaoyu.com/2519329010.html
作者
hcy
发布于
2019年12月25日
更新于
2024年8月17日
许可协议