在之前的文章里总结过《Spring中三大JSON框架的使用》,里面有提到Jackson的一些基本用法。最近遇到一个问题,就是需要把请求中的字符串进行一个trim,下面看一下怎么做。
一、自定义String类型的Deserializer
前面介绍过Jackson的核心就是ObjectMapper,通过它来决定反序列化时的一些规则。除了提供的一些configure方法来指定基础类型字段的解析规则,还可以通过注册Module来指定复杂类型(例如自定义的Class等)的解析规则。下面直接看代码,如何对String类型的字段解析后,去除头尾的空格。
|
|
可以看到,其实非常简单。
二、Deserializer的原理
2.1 deserialize方法的内部实现
看到上面自定义的Deserializer,就会想到一个问题,在没有自定义String类型的字段解析前,Jackson也是可以解析字符串类型的字段,自定义的时候也就很简单重写了一个deserialize方法,会不会导致解析出现什么其他的错误?
为了解答这个问题,要从Jackson的Default Deserializer说起,看下Jackson里面都有哪些StdDeserializer。

可以看到我们自定义的Deserializer也在最下面。
还是以String类型为例,Jackson自带一个StringDeserializer,先看一下它是怎么反序列化字符串的,它的deserialize方法源码如下(Jackson-2.8.8)。
|
|
可以看到比我们自定义的deserialize方法要复杂一些,仔细看会发现,它主要是考虑了多种情况,当传入的原始序列化的数据是一个JsonToken.VALUE_STRING时,那就简单的返回一个字符串;当原始的序列化的数据是一个ARRAY(带有[])或者OBJECT(带有{})时,而对应的反序列化的字段又是一个String时,它会相应地把ARRAY或者OBJECT转换成[...]或者{...}这样的字符串再返回。
所以可以确定的是,我们自定义的deserialize方法,在遇到原始数据不是一个简单的VALUE_STRING时,会返回null。具体在业务中是否可以接受,这个就要看个人需求了,请大家注意这一点。
2.2 如何调用Deserializer
再看一下Jackson是如何决定使用哪一个Deserializer来反序列化数据。简单看一下源代码(2.8.8版本),在BeanDeserializerFactory.java中有一个createBeanDeserializer方法,这里我不贴代码了,简单说一下逻辑:
- 根据字段的Type(这里是
String),查找CustomBeanDeserializer,如果找到了,那么直接返回。 - 如果没有Custom的
Deserializer,那么就查找StdDeserializer,按照上面贴的Jackson自带的Deserializer,这里就会返回StringDeserializer了。
因此可以确认如果对String类型的字段自定义了一个Deserializer,那么Jackson便不再会使用自带的StringDeserializer去反序列化数据了。如果想要确认这一点,在ide里面debug一下,便可证实。