今天碰到一个问题,后端使用LocalDate mDate接收,看起来很正常,但是后台一直接收不到参数,猜想是DateFormat(pattern = ‘yyyy-MM-dd’),结果还是不生效
发现是Jackson反序列化失败了
这里不会提示报错信息,仅仅映射不上值为null而已
:::info
我们知道,boolean属性使用is开头会存在冲突,原因就是boolean的set方法(比如使用Lombook等生成),会自动加入is开头
:::
那么第二个字母为大写,同样会产生此问题,原因就是Jasckson的反序列化是完全根据set方法反向寻找的
反序列化的时候获取属性,除去Boolen类型都是通过set***转换来的,转换的方法为:
1 | protected static String legacyManglePropertyName(final String basename, final int offset) |
如果不手动写明set而使用生成的,比如name属性生成为setName()
Jackson遍历set之后的名称,因为常规属性约定都是小写开头,所以以Name为例:
1 | for(遍历set剩余部分){ |
所以对应mDate的setMDate方法
第一个字母自动转,后续转小写,所以得到的属性是 ’mdate‘,所以前端传mDate是接收不到的
这也是为什么后端写MDATE,前端传MDATE也能接受到,原因是setmDate,找到第一个m,直接就自动返回全量了
所以只要是大写开头的属性,直接就返回了,前端一定能映射上,但是不符合命名规范,一般不会出现。
那么aaDate呢?setAaDate,A转小写,第二个a直接返回 = aaDate也能映射
所以注意第二个字符大写问题,命名规范上不建议第一个单词为单字母,至少为标准单词:两个字母以上。
改造
由于进行了包拆分,抽象基类需要放到公共服务包中,且pojo移动到了dto包,所以只能基类包引dto包是合理的,反之则不合理,因为接受请求属于是运行时操作,此时引入反序列化改造。

核心方法为deserialize,去获取Jackson对象的值转Json再转对象,但是此时有个坑,前端控件在第一次刷新进入时传给后端的是null,填写再清空此时传的json为 “”
当传值为""时,JSON.parseObject可以正常转换为LocalDate的null,但是如果是空,这里会抛出异常:
:::info
“DateTimeParseException: Text ‘null’ could not be parsed at index 0”
:::
很明显不允许从null,转向LocalDate类型,认为是不合法的JSON,难道是 起码应当有个""????
Debug

发现JsonNode(ObjectNode) 的元素,Json(LocalDate/String)默认解析的都是TextNode(“null”)
然后在writeValueAsString会转成:

所以"null"字符串是肯定不能转LocalDate的,所以 Text ‘null’ 指的是String文本
所以修复

置空json串达到效果
如果您喜欢此博客或发现它对您有用,则欢迎对此发表评论。 也欢迎您共享此博客,以便更多人可以参与。 如果博客中使用的图像侵犯了您的版权,请与作者联系以将其删除。 谢谢 !