Jackson 2.11.4 不支持反序列化 LocalDate,在 [@JsonFormat] 中设置 [lenient = OptBoolean.FALSE] 时模式为 [yyyy-MM-dd]?

Jackson 2.11.4 doesn't support deserialize LocalDate which pattern is [yyyy-MM-dd] when set [lenient = OptBoolean.FALSE] in [@JsonFormat]?

内容:

当我为类型为 LocalDate 的字段设置 @JsonFormat -> lenient = OptBoolean.FALSE 时,它显示 Unable to obtain LocalDate from TemporalAccessorjackson版本为2.11.4,SpringBoot版本为2.4.2.


详情:

我今天早上将SpringBoot升级到2.4.2,但是在反序列化一个类型为LocalDate的字段时,我的测试失败了。

这是我的代码:

package com.example.demo;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.OptBoolean;

import java.time.LocalDate;

public class Demo {

    public Demo(){}

    public Demo(LocalDate localDate){
        this.localDate = localDate;
    }

    @JsonFormat(pattern = "yyyy/MM/dd", lenient = OptBoolean.FALSE)
    private LocalDate localDate;

    public LocalDate getLocalDate() {
        return localDate;
    }

    public void setLocalDate(LocalDate localDate) {
        this.localDate = localDate;
    }
}

package com.example.demo;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class Controller {

    @GetMapping("/test")
    public ResponseEntity<String> test(@RequestBody Demo demo) {
        var localDate = demo.getLocalDate().toString();
        return ResponseEntity.ok(localDate);
    }
}

curl -L -X GET 'http://localhost:8080/test' \
-H 'Content-Type: application/json' \
--data-raw '{
    "localDate": "2020/01/15"
}'

显示

Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `java.time.LocalDate` from String "2020/01/15": Failed to deserialize java.time.LocalDate: (java.time.format.DateTimeParseException) Text '2020/01/15' could not be parsed: Unable to obtain LocalDate from TemporalAccessor: {YearOfEra=2020, MonthOfYear=1, DayOfMonth=15},ISO of type java.time.format.Parsed; nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.time.LocalDate` from String "2020/01/15": Failed to deserialize java.time.LocalDate: (java.time.format.DateTimeParseException) Text '2020/01/15' could not be parsed: Unable to obtain LocalDate from TemporalAccessor: {YearOfEra=2020, MonthOfYear=1, DayOfMonth=15},ISO of type java.time.format.Parsed
 at [Source: (PushbackInputStream); line: 2, column: 18] (through reference chain: com.example.demo.Demo["localDate"])]

但是当我将 lenient 设置为 TRUE 或删除注释时,效果很好。

有谁知道真正的原因吗?

我得到了答案。

当我们设置lenient = OptBoolean.FALSE时,它将对DateTimeFormatter使用严格模式。请参阅问题 jackson-modules-java8 #199 and jackson-modules-java8 #199

错误显示 Unable to obtain LocalDate from TemporalAccessor: {YearOfEra=2020, MonthOfYear=1, DayOfMonth=15}

java8 java.time.format.DateTimeFormatter中,这里有3行注释:

Symbol  Meaning                     Presentation      Examples
------  -------                     ------------      -------
 G       era                         text              AD; Anno Domini; A
 u       year                        year              2004; 04
 y       year-of-era                 year              2004; 04

它说 y 表示时代,u 实际表示年份。

因此将模式 yyyy-MM-dd 更新为 uuuu-MM-dd,它有效。

而如果要在花样中使用y,最好同时使用G来指定年代。

查看问题:https://github.com/FasterXML/jackson-modules-java8/issues/199