【常见问题】Java 8 date time type `java.time.LocalDateTime` not supported by default 日期序列化问题

问题描述

将一个包含LocalDateTime对象的集合进行序列化和反序列化时,可能会遇到以下异常:

Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: 
Java 8 date/time type `java.time.LocalDate` not supported by default: add Module 
"com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling (through reference chain: java.util.HashMap["data"])

这是因为Jackson库在默认情况下不支持LocalDateTime类型的序列化和反序列化。为了解决这个问题,我们需要自定义序列化和反序列化的行为。

解决方案一

1. 引入依赖

            <dependency>
                <groupId>com.fasterxml.jackson</groupId>
                <artifactId>jackson-datatype-jsr310</artifactId>
                <version>${jackson.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

2. 设定时间模块

        ObjectMapper objectMapper = new CustomObjectMapper();
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"));
        objectMapper.registerModule(new JavaTimeModule());
        Map<String, Object> map = new HashMap<>();
        map.put("time", LocalDateTime.now());
        map.put("data", LocalDate.now());
        objectMapper.writeValueAsString(map);

解决方案二

1. 自定义序列化器

首先,我们需要创建一个自定义的序列化器,用于处理LocalDateTime类型的序列化和反序列化。具体实现如下:

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
import java.time.LocalDateTime;

public class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
    @Override
    public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        gen.writeString(value.toString());
    }
}

在这个自定义序列化器中,我们将LocalDateTime对象转换为字符串,然后使用gen.writeString()方法将其写入JSON输出流。

接下来,我们需要将这个自定义序列化器应用到我们的实体类上。假设我们有一个名为Event的实体类,其中包含一个LocalDateTime类型的属性eventTime

import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.time.LocalDateTime;

public class Event {
    private String name;
    private LocalDateTime eventTime;

    // getter and setter methods ...

    @JsonSerialize(using = LocalDateTimeSerializer.class)
    public LocalDateTime getEventTime() {
        return eventTime;
    }

    public void setEventTime(LocalDateTime eventTime) {
        this.eventTime = eventTime;
    }
}

通过在getEventTime()方法上添加@JsonSerialize注解,并指定我们刚刚创建的自定义序列化器(Using = LocalDateTimeSerializer.class),我们可以确保在序列化和反序列化eventTime属性时,会使用我们定义的自定义序列化器。

2. 自定义反序列化器(可选)

如果我们希望在反序列化时保留LocalDateTime对象的类型信息,我们可以创建一个自定义的反序列化器。具体实现如下:

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
    private static final DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
    private static final LocalDateTime minValue = LocalDateTime.MIN;
    private static final LocalDateTime maxValue = LocalDateTime.MAX;
    private static final long serialVersionUID = 1L; // Add a unique ID to the deserializer if needed

    @Override
    public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        String value = p.getText();
        return LocalDateTime.parse(value, formatter); // Use the same formatter as in the serializer for consistency
    }
}

posted @ 2024-02-17 08:04  木头左  阅读(1885)  评论(0编辑  收藏  举报