说明
Jackson 对于常用的类型已经有默认的实现,但有时候可能并不能满足我们的需求,比如我想把 13 位数值型的毫秒值反序列化成 LocalDateTime ,这就需要我们自己去实现
常用的时间类型序列化反序列化器
时间类型转换器
时间类型序列化反序列化器,需要将一种类型的数据转换为时间类型,或者将时间类型的数据转换成其他类型。我们应该把这个转换操作提取出来,放到一个 时间类型转换类中,这样其他不走 Jackson 序列化反序列化的地方也可以复用转换的代码。
以下是我的时间类型转换类
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
/**
* 时间类型转换器
*/
public class DateTimeConverter {
public static final String YEAR_MONTH_DAY_HOUR_MINUTE_SECOND = "yyyy-MM-dd HH:mm:ss";
/**
* systemDefault() 会获取 jvm 的时区,如果没设置或更改过 jvm 的时区,则 jvm 默认使用操作系统的时区
*/
public static final ZoneId JVM_ZONE_ID = ZoneId.systemDefault();
/**
* yyyy-MM-dd HH:mm:ss 格式的 DateTimeFormatter
*/
public static final DateTimeFormatter yearMonthDayHourMinuteSecondFormatter =
DateTimeFormatter.ofPattern(YEAR_MONTH_DAY_HOUR_MINUTE_SECOND).withZone(JVM_ZONE_ID);
/**
* 将 13 位数值型的毫秒值转换为 yyyy-MM-dd HH:mm:ss 格式的字符串
*
* @param timestamp 13 位数值型的毫秒值
* @return
*/
public static String timestamp2YearMonthDayHourMinuteSecond(long timestamp) {
return timestamp2DateString(yearMonthDayHourMinuteSecondFormatter, timestamp);
}
/**
* 根据指定的 DateTimeFormatter 将 13 位数值型的毫秒值转换为 yyyy-MM-dd HH:mm:ss 格式的字符串
*
* @param formatter
* @param timestamp 13 位数值型的毫秒值
* @return
*/
public static String timestamp2DateString(DateTimeFormatter formatter, long timestamp) {
Instant instant = Instant.ofEpochMilli(timestamp);
return formatter.format(instant);
}
/**
* 将 13 位数值型的毫秒值转换为 LocalDateTime
*
* @param timestamp 13 位数值型的毫秒值
* @return
*/
public static LocalDateTime timestamp2LocalDateTime(long timestamp) {
Instant instant = Instant.ofEpochMilli(timestamp);
return LocalDateTime.ofInstant(instant, JVM_ZONE_ID);
}
/**
* 将 LocalDateTime 转换为 13 位数值型的毫秒值
*
* @param localDateTime 13 位数值型的毫秒值
* @return
*/
public static long localDateTime2Timestamp(LocalDateTime localDateTime) {
Instant instant = localDateTime.atZone(JVM_ZONE_ID).toInstant();
return instant.toEpochMilli();
}
}
LocateDateTime 序列化成 13 位数值型的毫秒值
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;
/**
* 将 LocateDateTime 序列化成 13 位数值型的毫秒值
*/
public class LocalDateTimeSerializerTimestamp extends JsonSerializer<LocalDateTime> {
@Override
public void serialize(LocalDateTime localDateTime, JsonGenerator gen, SerializerProvider serializers) throws IOException {
long timestamp = DateTimeConverter.localDateTime2Timestamp(localDateTime);
gen.writeNumber(timestamp);
}
}
13 位数值型的毫秒值反序列化成 LocalDateTime
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import java.io.IOException;
import java.time.LocalDateTime;
/**
* 将 13 位数值型的毫秒值反序列化成 LocalDateTime
*/
public class TimestampDeserializerLocalDateTime extends JsonDeserializer<LocalDateTime> {
@Override
public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
long timestamp = jsonParser.getLongValue();
return DateTimeConverter.timestamp2LocalDateTime(timestamp);
}
}
13 位数值型的毫秒值序列化为 yyyy-MM-dd HH:mm:ss 格式的字符串
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
/**
* 将 13 位数值型的毫秒值序列化为 yyyy-MM-dd HH:mm:ss 格式的字符串
*/
public class TimestampSerializerYearMonthDayHourMinuteSecond extends JsonSerializer<Long> {
@Override
public void serialize(Long timestamp, JsonGenerator gen, SerializerProvider serializers) throws IOException {
String dateTimeString = DateTimeConverter.timestamp2YearMonthDayHourMinuteSecond(timestamp);
gen.writeString(dateTimeString);
}
}
使用自定义的序列化反序列化器
在要序列化的字段上加 @JsonSerialize(using = 自定义的序列化器.class)
在要反序列化的字段上加 @JsonDeserialize(using = 自定义的反序列化器.class)
例如
public class DateVO {
@JsonSerialize(using = LocalDateTimeSerializerTimestamp.class)
@JsonDeserialize(using = TimestampDeserializerLocalDateTime.class)
private LocalDateTime localDateTime;
...
}