Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a Spring Boot flag to disable lenient Jackson parsing of LocalDate values with times?

Spring Boot defaults allow both dates and datetime values in LocalDate.

E.g. for following DTO:

public class Person {

  private LocalDate birthDate;

  //getter & setters
}

Both of the following are acceptable:

{
  "birthDate" : "2021-07-24"
}
{
  "birthDate" : "2021-07-24T17:00:00Z"
}

Jackson has a lenient flag that can be set to reject dates with time:

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

Is there a corresponding Spring Boot application properties flag that can be set to apply globally to all LocalDate fields, so that the annotation does not need to be added to every LocalDate field and without needing to define a custom deserializer like this?

like image 391
SGB Avatar asked Jul 24 '21 21:07

SGB


People also ask

Does spring boot have Jackson ObjectMapper?

Overview. When using JSON format, Spring Boot will use an ObjectMapper instance to serialize responses and deserialize requests. In this tutorial, we'll take a look at the most common ways to configure the serialization and deserialization options. To learn more about Jackson, be sure to check out our Jackson tutorial.

What is the use of ObjectMapper?

ObjectMapper provides functionality for reading and writing JSON, either to and from basic POJOs (Plain Old Java Objects), or to and from a general-purpose JSON Tree Model ( JsonNode ), as well as related functionality for performing conversions.

Should ObjectMapper be a bean?

Assuming no configuration is required, just a plain ObjectMapper will do. It's OK to be declared as static. But in environment like Spring, IMHO you should declare it as a bean.

Does spring boot use Jackson?

Auto-configuration for Jackson is provided and Jackson is part of spring-boot-starter-json . When Jackson is on the classpath an ObjectMapper bean is automatically configured. Several configuration properties are provided for customizing the configuration of the ObjectMapper .


1 Answers

Before addressing the question of setting the lenient flag globally, it's worth noting that setting this flag in this particular example (which was written in a version of Jackson prior to 2.13.0) is not what actually achieved the desired result. Rather, it is the presence of the pattern annotation element that caused the value to be rejected, not the lenient annotation element. The following would therefore be sufficient to reject the example datetime value:

@JsonFormat(pattern="uuuu-MM-dd")
private LocalDate birthDate;

Regarding the question of setting the lenient flag globally in a Spring Boot application, the answer to this question depends on the version of Spring Boot and Jackson being used, as newer versions of these libraries have added functionality around this behavior.

Spring Boot 2.6.0 and Jackson 2.13.0

Using Spring Boot 2.6.0 and Jackson 2.13.0, the spring.jackson.default-leniency application property can be set to false to achieve the desired result.

spring.jackson.default-leniency: false

Starting with Jackson 2.13.0, setting the lenient flag to false causes causes dates with times to be rejected when the underlying type is a date without a time (jackson-modules-java8#212).

Spring Boot 2.6.0 added the spring.jackson.default-leniency flag to configure the default leniency on the Spring Boot provided ObjectMapper bean (spring-boot#27547).

Therefore, combining these two library versions, and utilizing the spring.jackson.default-leniency flag achieves the desired result of rejecting dates with time components for LocalDate values.

Spring Boot 2.5.x (or earlier) and Jackson 2.13.0

Spring Boot 2.5.x does not have an application property to set the default leniency of the Spring Boot provided ObjectMapper bean. However, it is possible to customize this bean in other ways to set the default leniency. As noted above, this will achieve the desired result of rejecting dates with times in Jackson 2.13.x or later.

The most straightforward approach to setting the default leniency in a Spring Boot 2.5.x application is probably to use a custom Jackson2ObjectMapperBuilderCustomizer bean to configure the ObjectMapper:

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

Jackson 2.12.x (or earlier)

As noted above, setting the lenient flag to false does not actually cause Jackson versions prior to 2.13 to reject values with a time part.

like image 74
M. Justin Avatar answered Sep 25 '22 20:09

M. Justin