Core Java

How to Fix Jackson LocalDate JSON Parse Errors

Jackson is one of the most commonly used libraries for converting JSON data into Java objects and vice versa. When working with Java’s modern date and time API, developers may sometimes encounter an error similar to the following:

Cannot construct instance of `java.time.LocalDate`
Cannot deserialize value of type `java.time.LocalDate`

This usually happens when Jackson’s ObjectMapper does not know how to deserialize Java 8 date and time classes such as LocalDate and LocalDateTime. The solution is typically to register the JavaTimeModule, which provides Jackson with the necessary serializers and deserializers for the Java Time API.

1. Understanding the Problem

Consider the following JSON:

{
  "name": "John",
  "dateOfBirth": "1995-08-15",
  "lastLogin": "2026-09-06T10:30:00"
}

And the following Java class:

import java.time.LocalDate;
import java.time.LocalDateTime;

public class User {

    private String name;
    private LocalDate dateOfBirth;
    private LocalDateTime lastLogin;

    // Getters and setters
}

When Jackson tries to convert this JSON into a User object, an incorrectly configured ObjectMapper may fail because LocalDate and LocalDateTime require specific support for the Java Time API. Jackson can easily handle common types such as String, int, boolean, and collections out of the box. However, classes from the java.time package use a more specialized representation and are not handled by older or incorrectly configured Jackson setups automatically. As a result, you may see an exception similar to:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException:
Cannot construct instance of `java.time.LocalDate`

The problem is usually not with the JSON format itself. In this example, "1995-08-15" is a valid date representation for a LocalDate, and "2026-09-06T10:30:00" is a valid representation for a LocalDateTime. The actual issue is that the ObjectMapper does not know how to convert these JSON strings into Java Time objects. Jackson needs the appropriate Java Time module to provide the serializers and deserializers required for classes such as LocalDate and LocalDateTime. Once this support is configured, Jackson can correctly map the JSON date values to their corresponding Java types during deserialization and convert them back to JSON during serialization.

1.1 LocalDate vs LocalDateTime

LocalDate represents a date without a time or time-zone, such as 1995-08-15. LocalDateTime represents both a date and a time, such as 2026-09-06T10:30:00. Jackson uses different serializers and deserializers for these Java Time API types, which is why the JavaTimeModule is required when they are not already configured by the application framework.

1.2 Common Mistakes

  • Missing dependency: The jackson-datatype-jsr310 dependency is not available in the application.
  • Missing module registration: A manually created ObjectMapper does not have JavaTimeModule registered.
  • Incorrect JSON format: The JSON value does not match the expected LocalDate or LocalDateTime format.
  • Custom ObjectMapper: Replacing Spring Boot’s auto-configured ObjectMapper with a custom instance can accidentally remove automatically configured Jackson modules.

2. Code Example with LocalDate and LocalDateTime

2.1 Maven

To enable Jackson to work with Java Time API classes such as LocalDate and LocalDateTime, add the jackson-datatype-jsr310 dependency to your Maven project.

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
</dependency>

This dependency provides the JavaTimeModule, which contains the serializers and deserializers required by Jackson to correctly convert JSON date and time values into Java types such as LocalDate and LocalDateTime.

2.2 User.java

The User class represents the Java object that Jackson will create from the JSON data. It contains both LocalDate and LocalDateTime fields, which require Java Time support during JSON deserialization.

// User.java
import java.time.LocalDate;
import java.time.LocalDateTime;

public class User {

    private String name;
    private LocalDate dateOfBirth;
    private LocalDateTime lastLogin;

    public User() { }

    public User(String name, LocalDate dateOfBirth, LocalDateTime lastLogin) {
        this.name = name;
        this.dateOfBirth = dateOfBirth;
        this.lastLogin = lastLogin;
    }

    // Getters and Setters
}

The default constructor allows Jackson to create an instance of the User class, while the getters and setters allow it to access and populate the object fields. The dateOfBirth field stores only the date, whereas lastLogin stores both the date and time.

2.3 Jackson Example

The following example demonstrates how to configure ObjectMapper with JavaTimeModule and use it to deserialize JSON containing LocalDate and LocalDateTime fields. It also shows how to serialize a Java object containing these types back into JSON.

// JacksonDateExample.java
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

import java.time.LocalDate;
import java.time.LocalDateTime;

public class JacksonDateExample {

    public static void main(String[] args) throws Exception {

        String json = """
                {
                  "name": "John",
                  "dateOfBirth": "1995-08-15",
                  "lastLogin": "2026-09-06T10:30:00"
                }
                """;

        ObjectMapper objectMapper = new ObjectMapper();

        // Register support for LocalDate and LocalDateTime
        objectMapper.registerModule(new JavaTimeModule());

        // Convert JSON to Java object
        User user = objectMapper.readValue(json, User.class);

        System.out.println("Name: " + user.getName());
        System.out.println("Date of Birth: " + user.getDateOfBirth());
        System.out.println("Last Login: " + user.getLastLogin());

        // Convert Java object back to JSON
        User newUser = new User(
                "Alice",
                LocalDate.of(1998, 5, 20),
                LocalDateTime.of(2026, 9, 6, 14, 30)
        );

        String userJson = objectMapper.writeValueAsString(newUser);
		
        System.out.println("\nSerialized JSON:");
        System.out.println(userJson);
    }
}

2.3.1 Code Explanation

The example first imports ObjectMapper, JavaTimeModule, LocalDate, and LocalDateTime. A JSON string containing a user’s name, date of birth, and last login time is then created. The ObjectMapper is initialized and JavaTimeModule is registered to provide Jackson support for Java Time API classes. The readValue() method deserializes the JSON into a User object, converting the dateOfBirth and lastLogin values into LocalDate and LocalDateTime respectively. The program then prints the values from the resulting object. Next, a new User object is created using LocalDate.of() and LocalDateTime.of(). Finally, writeValueAsString() serializes this Java object back into a JSON string, demonstrating both deserialization and serialization with Java date and time types.

2.3.2 Code Output

When the program is executed, Jackson successfully deserializes the JSON into a User object and then serializes another User object back into JSON.

Name: John
Date of Birth: 1995-08-15
Last Login: 2026-09-06T10:30

Serialized JSON:
{"name":"Alice","dateOfBirth":"1998-05-20","lastLogin":"2026-09-06T14:30:00"}

The output confirms that LocalDate is represented using the yyyy-MM-dd format, while LocalDateTime uses the date and time format without a time-zone or offset. This conversion is handled by the serializers and deserializers provided by JavaTimeModule.

3. Conclusion

The Cannot construct instance of java.time.LocalDate error usually occurs because Jackson does not have the necessary support to handle Java Time API classes. The straightforward solution is to include the jackson-datatype-jsr310 dependency and register JavaTimeModule with your ObjectMapper. Once configured, Jackson can correctly deserialize and serialize LocalDate, LocalDateTime, and other Java Time classes, allowing your application to work with modern date and time types without JSON parsing errors.

Yatin Batra

An experience full-stack engineer well versed with Core Java, Spring/Springboot, MVC, Security, AOP, Frontend (Angular & React), and cloud technologies (such as AWS, GCP, Jenkins, Docker, K8).
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Back to top button