Backend Development 18 min read

Global Date and Time Conversion in Spring Boot: Custom Converters, Jackson Configuration, and Parameter Binding

This article explains how to globally configure date and time handling in Spring Boot 2.x, covering custom Converter beans for LocalDate, LocalDateTime, and LocalTime, Jackson JSON serialization settings, @InitBinder usage, and common pitfalls such as lambda expressions and parameter binding.

Top Architect
Top Architect
Top Architect
Global Date and Time Conversion in Spring Boot: Custom Converters, Jackson Configuration, and Parameter Binding

The article demonstrates how to configure global date and time conversion in a Spring Boot 2.x project, addressing common errors when using LocalDateTime and LocalDate in DTOs.

Goal : Enable request parameters (String) to be converted to Date objects for GET/POST requests, support Java 8 date API (LocalDate, LocalTime, LocalDateTime), and format JSON request/response bodies.

GET/POST Parameter Conversion

When a request parameter of type LocalDate lacks annotations, Spring MVC uses ModelAttributeMethodProcessor , which attempts to instantiate the target via reflection. Since LocalDate has no default constructor, conversion fails.

To solve this, a custom Converter is registered as a Spring bean:

@Configuration
public class DateConverterConfig {
    @Bean
    public Converter
localDateConverter() {
        return source -> LocalDate.parse(source, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
    }

    @Bean
    public Converter
localDateTimeConverter() {
        return source -> LocalDateTime.parse(source, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    }
}

These beans are injected into ParameterConversionService , allowing Spring to convert incoming strings to the appropriate Java 8 date types.

Pitfall with Lambda Expressions

Using a lambda to create the Converter can cause an IllegalArgumentException because Spring cannot determine the generic source and target types of the lambda. The stack trace shows the failure occurs during bean registration in FormattingConversionService .

Solution: Prefer the anonymous inner class implementation or ensure the lambda is registered after requestMappingHandlerAdapter is created, e.g., with @ConditionalOnBean(name = "requestMappingHandlerAdapter") .

JSON Request/Response Global Handling

For application/json requests, configure Jackson to use a uniform date‑time format:

@Configuration
public class JacksonConfig {
    public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
    public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";

    @Bean
    public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        mapper.setTimeZone(TimeZone.getTimeZone("GMT+8:00"));
        mapper.setDateFormat(new SimpleDateFormat(DEFAULT_DATE_TIME_FORMAT));
        JavaTimeModule module = new JavaTimeModule();
        module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)));
        module.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)));
        module.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));
        module.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)));
        module.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)));
        module.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));
        mapper.registerModule(module);
        converter.setObjectMapper(mapper);
        return converter;
    }
}

This configuration ensures that JSON bodies are serialized/deserialized using the specified patterns and supports Java 8 date/time types.

Partial (Field‑Level) Formatting

When a specific field requires a different format, use Spring’s @JsonFormat annotation:

@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date releaseDate;

Alternatively, create custom serializers/deserializers (e.g., DateJsonSerializer and DateJsonDeserializer ) and apply them with @JsonSerialize / @JsonDeserialize .

Debugging MVC Parameter Binding

The article walks through the Spring MVC call chain ( DispatcherServlet → RequestMappingHandlerAdapter → InvocableHandlerMethod → ArgumentResolver ) and shows how RequestParamMethodArgumentResolver uses WebDataBinder and ConversionService to convert request parameters, while RequestResponseBodyMethodProcessor relies on HttpMessageConverter (Jackson) for JSON bodies.

Understanding these pathways helps diagnose conversion issues and decide whether to implement a custom Converter (for query/path parameters) or adjust Jackson’s ObjectMapper (for JSON).

Conclusion

To convert incoming request data to desired date/time types, differentiate based on the parameter annotation: use custom Converter beans for @RequestParam / @PathVariable , and configure Jackson (via ObjectMapper or field‑level annotations) for @RequestBody . Avoid lambda‑based converters unless they are registered after the handler adapter is ready.

MVCSpring BootJacksonDate ConversionCustom ConverterJava 8 Time
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.