自定义 Jackson 序列化反序列化器

2,363 阅读3分钟

说明

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;
      ...
}