记一次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
| { "a":"a" }
{ "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"> <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值。