Jackson 2.11.4中@JsonFormat设lenient=OptBoolean.FALSE时LocalDate反序列化报错
问题根本原因
这个问题是Java 8+ 时间API的格式规则、Jackson严格解析逻辑,加上SpringBoot 2.4.2 自带的Jackson 2.11.4 版本的已知行为偏差共同触发的:
- Java 时间格式的符号定义里,
yyyy代表带纪元的年(YearOfEra),要解析出这个字段对应的合法年份,必须同时配套解析纪元(Era)字段,才不会有歧义;如果要用不需要纪元的ISO标准年,格式符号应该用uuuu。 - 当
@JsonFormat注解设置lenient = OptBoolean.FALSE时,Jackson会开启严格解析模式:此时DateTimeFormatter不会自动为缺失的Era字段补默认的公元(CE)值。解析输入字符串2020/01/15时,最终得到的TemporalAccessor对象只存了YearOfEra=2020、MonthOfYear=1、DayOfMonth=15三个字段,缺少推导LocalDate必需的Era字段值。 - 严格模式下的LocalDate反序列化逻辑不会自动补全缺失字段,直接抛出
Unable to obtain LocalDate from TemporalAccessor的异常。如果把lenient设为TRUE或者移除注解,格式化器回到宽松状态,会自动把缺失的Era字段补成默认的公元纪年,字段组合凑齐后就能正常生成LocalDate实例,也就不会报错。 - 升级SpringBoot前没碰到这个问题,是因为旧版本SpringBoot集成的Jackson jsr310模块,在严格模式下不会关掉Era字段的默认补全逻辑——这个行为调整是Jackson 2.11.x 版本的回归改动,后续Jackson版本已经修正了这个逻辑。
可落地的解决方法
- 直接调整格式字符串:把原来的
yyyy/MM/dd改成uuuu/MM/dd。这种格式对应的年字段是ISO标准的连续年,不需要配套Era字段,即使开启严格解析也能正常生成LocalDate,从根源上避免字段缺失问题。 - 保留现有格式字符串的前提下,在项目中注册自定义的Jackson时间模块,为对应格式的LocalDate反序列化器显式指定带默认Era配置的DateTimeFormatter,让严格模式下也能自动补全缺失的纪元字段。
- 不需要严格校验输入合法性的场景下,直接移除
lenient = OptBoolean.FALSE配置,或者将其设置为OptBoolean.TRUE,和旧版本的解析行为对齐。 - 升级Jackson核心依赖到2.12.0及以上版本,覆盖SpringBoot 2.4.2 自带的Jackson 2.11.4 版本,规避这个版本的回归bug。
内容的提问来源于stack exchange,提问作者Reckless
相关产品推荐
相关产品推荐

