使用OpenFeign时LocalDateTime反序列化失败的解决方法
前言
我在使用 OpenFeign
进行远程调用时,发现我的调用端报错 Cannot deserialize value of type
java.time.LocalDateTime from String "2022-09-13T11:34:36"
,下面是错误排查与修改的过程。
异常描述
OpenFeign使用Get远程调用服务时,返回的dto如果包含了 LocalDateTime
的话,会导致远程调用失败,报Failed to deserialize java.time.LocalDateTime: (java.time.format.DateTimeParseException) Text '2022-09-13T11:34:36' could not be parsed at index 10
错误。
异常产生的原因
查阅资料后发现,SpringBoot中默认使用Jackson做Json序列化和反序列化,服务器使用openFeign接收数据时将日期字符串转成LocalDateTime时,因为jsr310协议的默认的反序列化器格式是解析 2022-09-13T11:34:36
这样格式的字符串的。
查看源码可以知道,默认解析String字符串时,会以 DEFAULT_FORMATTER
的格式进行解析。
1 | if (_formatter == DEFAULT_FORMATTER) { |
而 DEFAULT_FORMATTER
默认使用的日期格式为下图的 ISO_LOCAL_DATE_TIME
我们可以看到是带字符 T 的。
但是在根据根据2.12版本的[modules-base#94]的更改,我们的String时间字符串要解析成LocalDateTime格式时,不仅要第十个字符为T,还需要以字符Z结尾(这里我也不知道为什么这样设计)。
继续追踪源码,发现因为我们第十个字符是T,导致反序列化解析失败。
上面代码的注释意思:
解析指定的文本。
这将解析为一个TemporalAccessor,确保文本被完全解析。
参数:
Text -要解析的文本,不是null
position -要解析的位置,更新为解析的长度和任何错误的索引,如果解析整个字符串,则为null
返回:
解析的结果,不是null
抛出:
DateTimeParseException:解析失败
DateTimeException:在解析日期或时间时发生错误
IndexOutOfBoundsException:位置无效
解决办法
在我们dto中,将我们的日期格式添加上以下代码
1 |
需要注意的是,一定要加 shape = JsonFormat.Shape.STRING
这个可以帮我们把T去掉。
加了之后我们在看debug看一下效果:
可以发现这里的T不见了,并且解析结果也是成功的,至此问题解决。
需要注意的是:如果你的实体类模块是与service分开的,你需要重新构建工程。比如说,你的实体类是放在xxx-domain模块下的话,你修改之后重启xxx-service模块是不会生效的,因为没有重构项目生成新的target