☰
Spring Boot中LocalDateTime序列化问题全解析:Jackson全局配置与避坑指南
2026/10/14 1:22:30 网站建设 项目流程

1. 问题背景与核心痛点拆解

1.1 一个看似简单却频繁踩坑的场景

但凡做过Java后端接口开发的人,几乎都遇到过这样的场景:定义了一个包含LocalDateTime类型字段的实体类,接口返回JSON数据时,前端收到的却是一个奇怪的数组或者带T的字符串,比如[2024,1,15,10,30,45]或者2024-01-15T10:30:45。前端同学一脸懵地跑过来问:“这个时间格式怎么解析?”而你打开Swagger一看,明明数据库里存的是正常的2024-01-15 10:30:45,怎么到了接口返回就变了样?

这个问题的根源在于Java 8引入的java.time包与Jackson默认的序列化机制之间存在“代沟”。Jackson作为Spring Boot默认的JSON处理库,在早期版本中并没有原生支持LocalDateTime这类新时间类型。如果没有显式配置,Jackson会退而求其次,使用内置的LocalDateTimeSerializer,而这个默认序列化器输出的格式往往不是我们想要的。

更让人头疼的是,这个问题在不同场景下表现还不一样:有时候是序列化(Java对象转JSON)出问题,有时候是反序列化(JSON转Java对象)出问题,有时候两者都有问题。而且Spring Boot版本不同、Jackson版本不同,默认行为也会有差异。我见过不少项目组在这个问题上反复折腾,每次新搭一个项目就要重新踩一遍坑。

1.2 为什么这个问题值得单独拿出来讲

有人可能会说,不就是加个注解的事吗?@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")往字段上一贴不就完了?确实,对于单个字段或者少量字段,这样做没问题。但实际项目中的情况往往更复杂:

  • 项目中有几十上百个实体类都包含时间字段,逐个加注解工作量巨大且容易遗漏
  • 有些字段需要不同的时间格式,比如有些要精确到秒,有些要精确到毫秒
  • 全局配置和局部注解可能产生冲突,导致预期之外的结果
  • 前后端联调时,时间格式不统一导致解析失败,排查起来费时费力
  • 数据库查询、Redis缓存、消息队列等多个环节都可能涉及时间序列化

所以这个问题看似小,实际上牵涉到项目配置的全局观、Jackson的工作机制、Spring Boot的自动配置原理等多个层面。把它彻底搞清楚,不仅能解决眼前的问题,还能在遇到其他序列化问题时举一反三。

1.3 本文能帮你解决什么

接下来我会从Jackson的序列化机制讲起,把LocalDateTime序列化问题的来龙去脉说清楚,然后给出几种不同场景下的解决方案,包括全局配置、局部注解、自定义序列化器等。每种方案我都会说明适用场景和优缺点,你可以根据自己的项目情况选择。最后还会分享一些我在实际项目中踩过的坑和排查技巧,希望能帮你少走弯路。

2. Jackson序列化机制与LocalDateTime的冲突根源

2.1 Jackson是如何处理时间类型的

要理解问题,先得知道Jackson是怎么工作的。Jackson在序列化一个Java对象时,会为每个类型查找对应的JsonSerializer。对于java.util.Date类型,Jackson有专门的DateSerializer,它会根据配置的DateFormat来格式化输出。但对于java.time.LocalDateTime,情况就不同了。

在Jackson 2.8之前,java.time包的类型根本没有内置支持,你需要额外引入jackson-datatype-jsr310模块。从Jackson 2.8开始,这个模块被整合进了核心库,但默认情况下ObjectMapper并不会自动注册这些序列化器。Spring Boot通过自动配置帮我们做了这件事,但默认行为可能不符合预期。

具体来说,当Jackson遇到LocalDateTime字段时,如果没有找到合适的序列化器,它会尝试使用BeanSerializer把对象当作普通Bean来处理,这就导致了输出变成数组或者字段展开的奇怪格式。而jackson-datatype-jsr310模块提供了LocalDateTimeSerializer,但它默认使用的是ISO-8601格式,也就是带T的那种。

2.2 默认行为为什么不符合预期

Spring Boot的JacksonAutoConfiguration会自动注册JavaTimeModule,这个模块包含了java.time类型的序列化器和反序列化器。但问题在于,JavaTimeModule的默认配置是:

  • 序列化时使用ISO-8601格式,例如2024-01-15T10:30:45
  • 反序列化时也只接受ISO-8601格式
  • 如果配置了spring.jackson.date-format,这个配置只对java.util.Date生效,对LocalDateTime无效

这就解释了为什么很多人在application.yml里配置了spring.jackson.date-format=yyyy-MM-dd HH:mm:ss,但LocalDateTime字段依然输出带T的格式。因为那个配置项根本管不到java.time包的类型。

另外,WRITE_DATES_AS_TIMESTAMPS这个特性也会影响输出。如果开启了这个特性,时间会被序列化为时间戳数组;如果关闭,则输出ISO字符串。Spring Boot默认是关闭的,所以输出的是ISO字符串。

2.3 序列化与反序列化的双向问题

很多人只关注了序列化(出参)的问题,忽略了反序列化(入参)同样重要。假设前端传过来一个JSON:

{ "appointmentTime": "2024-01-15 10:30:45" }

如果后端没有配置对应的反序列化器,Jackson会尝试用默认的LocalDateTimeDeserializer来解析,而它只认ISO格式,遇到空格分隔的格式就会抛出InvalidFormatException。这个异常在Spring MVC中通常会被包装成HttpMessageNotReadableException,返回400错误,前端看到的可能只是一句“Bad Request”,排查起来相当费劲。

所以完整的解决方案必须同时覆盖序列化和反序列化两个方向,只解决一半等于没解决。

3. 全局配置方案:一劳永逸的解决思路

3.1 通过Jackson2ObjectMapperBuilderCustomizer定制

在Spring Boot项目中,最优雅的全局配置方式是使用Jackson2ObjectMapperBuilderCustomizer。这个接口允许你在Spring Boot自动配置的ObjectMapper基础上进行定制,而不需要完全替换它。

具体做法是定义一个配置类,实现Jackson2ObjectMapperBuilderCustomizer接口,在customize方法中注册自定义的序列化器和反序列化器:

@Configuration public class JacksonConfig { 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 Jackson2ObjectMapperBuilderCustomizer jacksonCustomizer() { return builder -> { builder.serializerByType(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DATE_TIME_PATTERN))); builder.deserializerByType(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DATE_TIME_PATTERN))); builder.serializerByType(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DATE_PATTERN))); builder.deserializerByType(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DATE_PATTERN))); builder.serializerByType(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(TIME_PATTERN))); builder.deserializerByType(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(TIME_PATTERN))); }; } }

这种方式的优势在于它保留了Spring Boot的其他自动配置,只在你指定的类型上覆盖默认行为。而且serializerByType和deserializerByType是成对出现的,保证了序列化和反序列化格式一致。

3.2 直接替换ObjectMapper的注意事项

有些教程会建议直接定义一个@Bean来替换整个ObjectMapper:

@Bean public ObjectMapper objectMapper() { ObjectMapper mapper = new ObjectMapper(); JavaTimeModule module = new JavaTimeModule(); module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(...)); module.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(...)); mapper.registerModule(module); return mapper; }

这种做法我不是很推荐,因为它会覆盖Spring Boot自动配置的ObjectMapper,导致一些默认配置丢失,比如FAIL_ON_UNKNOWN_PROPERTIES的关闭、PropertyNamingStrategy的配置等。如果你确实需要完全控制ObjectMapper,建议用@Primary注解并手动复制Spring Boot的默认配置,但这样做维护成本较高。

提示:优先选择Jackson2ObjectMapperBuilderCustomizer,它是在Spring Boot默认配置基础上的增强,而不是替换。

3.3 配置文件方式的局限性

在application.yml中配置spring.jackson.date-format和spring.jackson.time-zone是最简单的方式,但正如前面所说,这些配置对java.time类型无效。它们只对java.util.Date和Calendar生效。

如果你项目中还在使用java.util.Date,可以这样配置:

spring: jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT+8

但对于LocalDateTime,还是得靠代码配置。所以我的建议是:如果项目中同时存在Date和LocalDateTime,两者都要配置,不要指望一个配置项能覆盖所有情况。

4. 局部注解方案:灵活控制单个字段

4.1 @JsonFormat注解的正确用法

当只有少数几个字段需要特殊格式时,使用@JsonFormat注解是最直接的方式:

public class AppointmentVO { @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private LocalDateTime appointmentTime; @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") private LocalDate appointmentDate; }

这里有几个细节需要注意:

  • pattern指定格式,必须与前端约定一致
  • timezone指定时区,对于LocalDateTime来说,时区设置其实不会改变值,但加上可以避免一些边界问题
  • 注解可以放在字段上,也可以放在getter方法上,放在字段上更直观

@JsonFormat的优点是精确控制,哪个字段需要什么格式一目了然。缺点是如果字段多了,重复的注解会显得很冗余,而且容易遗漏。

4.2 全局配置与局部注解的优先级

当全局配置和局部注解同时存在时,局部注解的优先级更高。也就是说,如果你在配置类中全局设置了yyyy-MM-dd HH:mm:ss,但某个字段上加了@JsonFormat(pattern = "yyyy-MM-dd"),那么这个字段会按照yyyy-MM-dd来序列化。

这个特性可以用来处理特殊情况。比如大部分时间字段需要精确到秒,但某个报表字段只需要日期,就可以单独加注解覆盖全局配置。

但要注意,反序列化时同样遵循这个优先级。如果前端传的格式和注解指定的格式不匹配,依然会报错。所以前后端一定要约定好每个字段的格式,不能想当然。

4.3 自定义序列化器的编写要点

对于更复杂的需求,比如需要根据不同的业务场景输出不同的时间格式,或者需要在序列化时做一些额外的处理(比如时间戳转换、时区转换),可以编写自定义序列化器:

public class CustomLocalDateTimeSerializer extends JsonSerializer<LocalDateTime> { private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); @Override public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException { if (value == null) { gen.writeNull(); return; } gen.writeString(value.format(FORMATTER)); } }

对应的反序列化器:

public class CustomLocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> { private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); @Override public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { String text = p.getText().trim(); if (text.isEmpty()) { return null; } return LocalDateTime.parse(text, FORMATTER); } }

然后在字段上使用@JsonSerialize和@JsonDeserialize注解指定:

@JsonSerialize(using = CustomLocalDateTimeSerializer.class) @JsonDeserialize(using = CustomLocalDateTimeDeserializer.class) private LocalDateTime createTime;

自定义序列化器的好处是灵活性最高,可以在里面加日志、做兼容处理、支持多种格式解析等。缺点是需要写的代码更多,而且如果每个字段都这么搞,代码会显得很臃肿。所以通常只在全局配置无法满足需求时才使用。

5. 完整实操流程与关键环节实现

5.1 项目环境准备与依赖确认

在开始配置之前,先确认项目中的依赖情况。如果你使用的是Spring Boot 2.x或3.x,spring-boot-starter-web已经包含了jackson-datatype-jsr310,不需要额外引入。但如果你使用的是较老的Spring Boot 1.x,可能需要手动添加:

<dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jsr310</artifactId> </dependency>

确认依赖后,可以通过以下代码检查当前ObjectMapper是否已经注册了JavaTimeModule:

@Autowired private ObjectMapper objectMapper; @PostConstruct public void checkModules() { objectMapper.getRegisteredModuleIds().forEach(id -> System.out.println("Registered module: " + id)); }

如果输出中包含jackson-datatype-jsr310,说明模块已经注册。如果没有,需要手动注册。

5.2 全局配置类的完整实现

下面是一个完整的全局配置类,涵盖了LocalDateTime、LocalDate、LocalTime三种类型的序列化和反序列化:

@Configuration public class JacksonGlobalConfig { public static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss"; public static final String DATE_FORMAT = "yyyy-MM-dd"; public static final String TIME_FORMAT = "HH:mm:ss"; @Bean public Jackson2ObjectMapperBuilderCustomizer customJackson() { return builder -> { DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(DATE_TIME_FORMAT); DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(DATE_FORMAT); DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern(TIME_FORMAT); builder.serializerByType(LocalDateTime.class, new LocalDateTimeSerializer(dateTimeFormatter)); builder.deserializerByType(LocalDateTime.class, new LocalDateTimeDeserializer(dateTimeFormatter)); builder.serializerByType(LocalDate.class, new LocalDateSerializer(dateFormatter)); builder.deserializerByType(LocalDate.class, new LocalDateDeserializer(dateFormatter)); builder.serializerByType(LocalTime.class, new LocalTimeSerializer(timeFormatter)); builder.deserializerByType(LocalTime.class, new LocalTimeDeserializer(timeFormatter)); builder.simpleDateFormat(DATE_TIME_FORMAT); }; } }

这段代码的关键点在于:

  • 使用Jackson2ObjectMapperBuilderCustomizer而不是直接替换ObjectMapper
  • 为每种时间类型分别指定格式,避免一刀切
  • 最后一行simpleDateFormat是为了兼容java.util.Date类型

5.3 验证配置是否生效

配置完成后,写一个简单的测试接口来验证:

@RestController @RequestMapping("/api/test") public class TimeTestController { @GetMapping("/time") public Map<String, Object> getTime() { Map<String, Object> result = new HashMap<>(); result.put("localDateTime", LocalDateTime.now()); result.put("localDate", LocalDate.now()); result.put("localTime", LocalTime.now()); result.put("date", new Date()); return result; } @PostMapping("/time") public String postTime(@RequestBody TimeDTO dto) { return "Received: " + dto.getLocalDateTime(); } }

启动项目后,访问GET /api/test/time,观察返回的JSON格式。如果localDateTime输出为2024-01-15 10:30:45这样的格式,说明序列化配置生效。然后发送一个POST请求,Body为:

{ "localDateTime": "2024-01-15 10:30:45" }

如果接口正常返回,说明反序列化也配置成功。

5.4 不同Spring Boot版本的差异处理

Spring Boot 2.x和3.x在Jackson配置上有一些细微差异。Spring Boot 3.x默认使用Jackson 2.14+,对java.time的支持更加完善,但默认行为依然是ISO格式。配置方式与2.x基本一致,但需要注意Jakarta EE的包名变化。

另外,Spring Boot 3.x中spring.jackson.date-format的默认值可能有所不同,建议显式配置。如果你从2.x升级到3.x,建议重新检查一遍时间序列化的配置,确保行为一致。

对于使用WebFlux的项目,配置方式略有不同,需要关注ServerCodecConfigurer的配置。但核心思路是一样的:注册自定义的序列化器和反序列化器。

6. 常见问题与排查技巧实录

6.1 配置了但不生效的几种原因

这是最常见的问题:明明按照教程配置了,但输出格式还是不对。根据我的经验,原因通常有以下几种:

问题现象可能原因排查方法
输出带T的ISO格式配置类未被扫描到检查配置类是否在启动类的包路径下
输出时间戳数组WRITE_DATES_AS_TIMESTAMPS未关闭检查是否手动开启了该特性
部分接口生效部分不生效存在多个ObjectMapper检查是否有其他地方定义了ObjectMapper Bean
反序列化报错格式不匹配检查前端传的格式与配置的格式是否一致
时区差8小时时区配置问题检查JVM时区和Jackson时区配置

其中“存在多个ObjectMapper”是最隐蔽的问题。有些项目引入了第三方库,这些库可能自己定义了一个ObjectMapper,导致Spring MVC使用的不是你配置的那个。排查方法是注入ObjectMapper并打印它的hashCode,看看是否和预期一致。

6.2 前后端时间格式约定不一致怎么办

这个问题在前后端联调时特别常见。后端配置的是yyyy-MM-dd HH:mm:ss,前端传的是yyyy/MM/dd HH:mm:ss,结果反序列化直接报错。

解决思路有两种:

第一种是严格约定格式,前后端都按照同一个格式来。这需要团队有明确的接口规范文档,并且在代码审查时检查。

第二种是让反序列化器兼容多种格式。可以在自定义反序列化器中尝试多种格式解析:

public class FlexibleLocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> { private static final List<DateTimeFormatter> FORMATTERS = Arrays.asList( DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"), DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"), DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"), DateTimeFormatter.ISO_LOCAL_DATE_TIME ); @Override public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { String text = p.getText().trim(); if (text.isEmpty()) { return null; } for (DateTimeFormatter formatter : FORMATTERS) { try { return LocalDateTime.parse(text, formatter); } catch (DateTimeParseException ignored) { // 继续尝试下一个格式 } } throw new IOException("无法解析时间格式: " + text); } }

这种兼容性处理在对接第三方系统时特别有用,因为你不一定能要求对方改格式。

6.3 数据库查询与JSON输出的格式差异

有时候会遇到这样的情况:从数据库查出来的时间是2024-01-15 10:30:45,但接口返回变成了2024-01-15T10:30:45。这是因为数据库驱动把时间读成了LocalDateTime对象,而Jackson序列化时用了默认的ISO格式。

这个问题本质上还是序列化配置的问题,按照前面的全局配置方案就能解决。但需要注意的是,如果你使用的是MyBatis或JPA,它们可能有自己的类型处理器,确保类型处理器不会干扰Jackson的序列化。

另外,如果使用了Redis缓存,缓存中的时间格式也可能与接口输出不一致。这时候需要确保缓存序列化器和Jackson序列化器使用相同的格式配置。

6.4 几个容易忽略的细节

第一个细节是null值的处理。当LocalDateTime字段为null时,默认会输出null,这通常没问题。但如果你配置了@JsonInclude(JsonInclude.Include.NON_NULL),那么该字段会直接从JSON中消失,前端可能因此报错。所以要么保证字段不为空,要么和前端约定好空值的处理方式。

第二个细节是@JsonFormat注解的timezone属性。对于LocalDateTime来说,设置时区其实不会改变值,因为LocalDateTime本身不包含时区信息。但如果你用的是ZonedDateTime或OffsetDateTime,时区设置就很重要了。

第三个细节是Spring Boot的spring.jackson.serialization.write-dates-as-timestamps配置。这个配置如果设为true,所有时间都会输出为时间戳,包括LocalDateTime。所以如果你发现输出变成了数组,检查一下这个配置。

注意:在微服务架构中,如果多个服务之间通过HTTP调用传递时间字段,务必确保所有服务的时间序列化配置一致,否则会出现A服务发出的时间B服务解析不了的情况。

7. 不同场景下的方案选型建议

7.1 新项目从零搭建时的最佳实践

如果是新项目,我建议一开始就把时间序列化的全局配置做好。具体来说:

  • 在common模块中定义统一的JacksonConfig配置类
  • 约定统一的时间格式:yyyy-MM-dd HH:mm:ss
  • 同时配置LocalDateTime、LocalDate、LocalTime和Date四种类型
  • 在接口文档中明确标注时间字段的格式
  • 编写单元测试验证序列化和反序列化行为

这样做的好处是后续新增字段时不需要额外配置,减少遗漏。而且统一格式后,前端处理起来也方便。

7.2 老项目改造时的渐进式方案

对于已经在运行的老项目,直接改全局配置可能会影响现有接口,导致前端解析失败。这时候可以采用渐进式方案:

第一步,先添加全局配置,但保留原有的@JsonFormat注解。由于注解优先级更高,原有字段的行为不会改变。

第二步,新增的字段统一使用全局配置的格式,不再单独加注解。

第三步,逐步移除旧的@JsonFormat注解,统一到全局配置。每移除一个,就测试对应的接口,确保前端能正常解析。

第四步,全部迁移完成后,清理不再需要的自定义序列化器。

这种渐进式改造的风险最小,但周期较长。如果项目紧急,也可以选择只对新接口生效,老接口保持原样。

7.3 微服务架构下的统一配置策略

在微服务架构中,时间格式的统一更加重要。我的建议是:

  • 将Jackson配置类放在公共依赖中,所有服务引入同一个依赖
  • 如果使用Spring Cloud Gateway,确保网关层不会修改时间格式
  • 服务间调用使用Feign或RestTemplate时,确保编解码器配置一致
  • 在API网关层做统一的格式校验,拦截格式不正确的请求

另外,如果使用了消息队列传递包含时间的消息,消息的序列化和反序列化也要使用相同的配置。否则消费者解析不了生产者发出的消息,排查起来会很麻烦。

7.4 与前端框架的配合要点

前端方面,不同的框架对时间格式的处理方式不同。比如:

  • Vue + Element UI的日期选择器默认输出yyyy-MM-dd HH:mm:ss格式
  • React + Ant Design的DatePicker输出的是Dayjs对象,需要手动格式化
  • 原生JavaScript的toISOString()输出的是ISO格式

所以后端配置的时间格式最好与前端组件的默认输出保持一致,减少转换环节。如果无法一致,前端需要在提交前做格式化处理。

我个人的经验是,在接口文档中明确写出时间格式的示例,比如"appointmentTime": "2024-01-15 10:30:45",这样前端一看就知道该怎么传。比只写“时间格式:yyyy-MM-dd HH:mm:ss”要直观得多。

8. 实操心得与避坑经验分享

8.1 我踩过的几个典型坑

第一个坑是配置类的位置问题。有一次我把JacksonConfig放在了config包下,但启动类的包路径是com.example.app,而config包在com.example.config,结果配置类没有被扫描到,排查了半天才发现是包路径问题。所以配置类一定要放在启动类能扫描到的包路径下。

第二个坑是多个ObjectMapper实例的问题。项目中引入了一个第三方SDK,它自己创建了一个ObjectMapper并注册为Bean,导致Spring MVC使用了那个ObjectMapper而不是我配置的。后来通过@Primary注解指定了我自己的ObjectMapper才解决。

第三个坑是时区问题。服务器时区是UTC,但业务需要东八区时间。虽然LocalDateTime本身不带时区,但在某些数据库驱动和序列化器的组合下,会出现时间偏移。后来在JVM启动参数中加了-Duser.timezone=Asia/Shanghai才彻底解决。

8.2 性能方面的考量

自定义序列化器对性能的影响微乎其微,因为DateTimeFormatter是线程安全的,可以复用。但要注意不要在serialize方法中每次都创建新的DateTimeFormatter,那样会增加GC压力。

另外,如果接口返回大量包含时间字段的数据,序列化的开销会累积。在这种情况下,可以考虑使用@JsonIgnore排除不需要返回的时间字段,或者使用DTO只返回必要的字段。

8.3 测试用例的编写建议

时间序列化的测试很容易被忽略,但一旦出问题就是线上问题。建议至少编写以下测试用例:

  • 序列化测试:验证LocalDateTime对象转JSON后的格式是否正确
  • 反序列化测试:验证标准格式的JSON字符串能否正确转为LocalDateTime
  • 边界测试:验证null值、空字符串、非法格式的处理
  • 兼容性测试:验证多种格式的输入都能正确解析

使用ObjectMapper的writeValueAsString和readValue方法就可以完成这些测试,不需要启动整个Spring上下文。

8.4 后续扩展思路

如果项目中有国际化需求,时间格式可能需要根据用户的语言环境动态调整。这时候可以在自定义序列化器中根据LocaleContextHolder获取当前语言环境,然后选择对应的格式。

另外,如果项目中使用了@JsonComponent注解,可以将序列化器注册为Spring Bean,这样可以在序列化器中注入其他依赖,比如配置服务、日志服务等。这种方式比直接new一个序列化器更灵活。

最后,如果团队中多个项目都需要这套配置,可以把它封装成一个Spring Boot Starter,其他项目引入依赖即可自动配置。这样既保证了统一性,又减少了重复代码。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询