进阶规范:自定义序列化器解决 Long 精度丢失与日期格式化

5 阅读1分钟

前言

在 Java 项目中,后端默认的序列化方式往往无法完全满足前端的需求。最典型的场景有两个:

  1. Long 型精度丢失:Java 的 Long 长度超过 17 位时,前端 JavaScript 会产生精度丢失(如 Snowflake ID)。
  2. 日期格式不统一:默认序列化通常会返回 ISO 格式(如 2023-10-01T10:00:00),而前端往往需要 yyyy-MM-dd HH:mm:ss

ObjectMapper

ObjectMapper 是 Jackson 的核心序列化 / 反序列化类。

在 SpringBoot 中默认会通过 JacksonAutoConfiguration 注册一个 ObjectMapper 的 Bean,用于大多数序列化场景。

在项目中,我们可以还直接注入改 Bean 使用其序列化和反序列化能力,基本使用方式如下:

public class MapperUseCase {

    public static void main(String[] args) {
        SimpleModule simpleModule = new SimpleModule();
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        simpleModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(dateTimeFormatter));
        simpleModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(dateTimeFormatter));

        JsonMapper jsonMapper = JsonMapper.builder()
                .addModule(simpleModule)
                .build();

        jsonMapper.writeValue(System.out, LocalDateTime.now());

    }

}

在项目中配置与前端交互的格式

@AutoConfiguration
@ConditionalOnClass(ObjectMapper.class)
public class JacksonConfiguration {

    private static final String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";

    private static final String DATE_PATTERN = "yyyy-MM-dd";

    private static final String TIME_PATTERN = "HH:mm:ss";

    @Bean
    public SimpleModule jacksonWebmodule() {
        SimpleModule module = new SimpleModule();
        // Long 类型转 String,防止前端精度丢失
        module.addSerializer(Long.class, ToStringSerializer.instance);
        module.addSerializer(Long.TYPE, ToStringSerializer.instance);

        // LocalDateTime 格式化
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(DATE_TIME_PATTERN);
        module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(dateTimeFormatter));
        module.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(dateTimeFormatter));

        // LocalDate 格式化
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(DATE_PATTERN);
        module.addSerializer(LocalDate.class, new LocalDateSerializer(dateFormatter));
        module.addDeserializer(LocalDate.class, new LocalDateDeserializer(dateFormatter));

        // LocalTime 格式化
        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern(TIME_PATTERN);
        module.addSerializer(LocalTime.class, new LocalTimeSerializer(timeFormatter));
        module.addDeserializer(LocalTime.class, new LocalTimeDeserializer(timeFormatter));

        return module;
    }

}

这样就接口就可以按照设定的格式返回数据了!