是否有 Spring Boot 标志来禁用宽松的 Jackson 对 LocalDate 值与时间的解析?

SGB*_*SGB 5 java date-parsing date-formatting jackson spring-boot

Spring Boot 默认允许LocalDate.

例如对于以下 DTO:

public class Person {

  private LocalDate birthDate;

  //getter & setters
}
Run Code Online (Sandbox Code Playgroud)

以下两种情况都是可以接受的:

{
  "birthDate" : "2021-07-24"
}
Run Code Online (Sandbox Code Playgroud)
{
  "birthDate" : "2021-07-24T17:00:00Z"
}
Run Code Online (Sandbox Code Playgroud)

Jackson 有一个lenient可以设置为拒绝日期和时间的标志:

@JsonFormat(pattern="uuuu-MM-dd", lenient = OptBoolean.FALSE)
private LocalDate birthDate;
Run Code Online (Sandbox Code Playgroud)

是否有相应的 Spring Boot 应用程序属性标志可以设置为全局应用于所有LocalDate字段,以便不需要将注释添加到每个LocalDate字段,也不需要像这样定义自定义反序列化器?

M. *_*tin 6

在解决全局设置标志的问题之前lenient,值得注意的是,在这个特定示例(在 2.13.0 之前的 Jackson 版本中编写)中设置此标志并没有真正达到预期的结果。pattern相反,导致值被拒绝的是注释元素的存在,而不是lenient注释元素。因此,以下内容足以拒绝示例日期时间值:

@JsonFormat(pattern="uuuu-MM-dd")
private LocalDate birthDate;
Run Code Online (Sandbox Code Playgroud)

关于在 Spring Boot 应用程序中全局设置标志的问题lenient,这个问题的答案取决于所使用的 Spring Boot 和 Jackson 的版本,因为这些库的较新版本已经添加了围绕此行为的功能。

Spring Boot 2.6.0 和 Jackson 2.13.0

使用 Spring Boot 2.6.0 和 Jackson 2.13.0,spring.jackson.default-leniency可以将应用程序属性设置false为达到所需的结果。

spring.jackson.default-leniency: false
Run Code Online (Sandbox Code Playgroud)

从 Jackson 2.13.0 开始,当基础类型是不带时间的日期时,设置lenient标志导致带时间的日期被拒绝 ( jackson-modules-java8#212 )。false

Spring Boot 2.6.0 添加了spring.jackson.default-leniency标志来配置 Spring Boot 提供的ObjectMapperbean 上的默认宽松度 ( spring-boot#27547 )。

因此,结合这两个库版本并利用该spring.jackson.default-leniency标志可以实现拒绝具有时间分量的日期值的预期结果LocalDate

Spring Boot 2.5.x(或更早版本)和 Jackson 2.13.0

Spring Boot 2.5.x 没有应用程序属性来设置 Spring Boot 提供的ObjectMapperbean 的默认宽松度。但是,可以通过其他方式自定义此 bean 以设置默认的宽大程度。如上所述,这将达到在 Jackson 2.13.x 或更高版本中拒绝带有时间的日期的预期结果。

在 Spring Boot 2.5.x 应用程序中设置默认宽松度的最直接方法可能是使用自定义Jackson2ObjectMapperBuilderCustomizerbean 来配置ObjectMapper

@Configuration
public class CustomizedJacksonConfiguration {
    @Bean
    public Jackson2ObjectMapperBuilderCustomizer nonLenientObjectMapperBuilderCustomizer() {
        return builder -> builder.postConfigurer(
                objectMapper -> objectMapper.setDefaultLeniency(false));
    }
}
Run Code Online (Sandbox Code Playgroud)

Jackson 2.12.x(或更早版本)

如上所述,将lenient标志设置为false实际上不会导致 2.13 之前的 Jackson 版本拒绝带有时间部分的值。


pir*_*rho 1

我不知道是否有这样的属性,但您可以通过配置您的ObjectMapper. 配置类(就像这里)需要几行代码,但最好有一些代码,以防万一还有其他东西需要全局配置。

看一下这个配置类:

@Configuration
public class JacksonConfiguration {
    public static final String LOCAL_DATE_PATTERN = "yyyy-MM-dd";

    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        JavaTimeModule timeModule = new JavaTimeModule();
        timeModule.addDeserializer(LocalDate.class,
                new LocalDateDeserializer(DateTimeFormatter
                        .ofPattern(LOCAL_DATE_PATTERN)));
        mapper.registerModule(timeModule);
        return mapper;
    }
}
Run Code Online (Sandbox Code Playgroud)

Jackson 用来JavaTimeModule解析LocalDate(and LocalDateTime)。JavaTimeModule包括默认的反序列化器,并且似乎没有直接的方法来访问它们,因此技巧是替换反序列化器LocalDate。在示例中将模式显式设置为 1 时,如果给定的时间范围内也有时间,则会导致解析错误LocalDate(Time)

正如您所看到的,似乎需要一个自定义反序列化器,但在配置类上设置它并不是什么大问题。