【常见问题】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
}
}