【Jackson 填坑日记】“java.time.LocalDateTime not supported by default” 全场景解决方案

【Jackson 填坑日记】“java.time.LocalDateTime not supported by default” 全场景解决方案

作者:@Neoest
时间:2025-07-30
关键词:Jackson, java.time.LocalDateTime, JSR-310, Spring Boot, JSON 序列化

1. 问题现场

昨晚上线新版本的考试系统,一调用「试卷详情接口」就 500:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: 
Java 8 date/time type `java.time.LocalDateTime` not supported by default:
add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling
(through reference chain: com.yunjian.examination.vo.ExamPaperVO["generateTime"])

因为是生产环境,没有办法搞到具体异常截图,回顾了下,错误信息跟上面的一模一样

2. 先定位代码

出问题的 VO 很简单:

@Data
public class ExamPaperVO {
    private Long id;
    private String title;
    private LocalDateTime generateTime; // 这里炸了
}

Controller 直接返回:

@GetMapping("/{id}")
public ExamPaperVO detail(@PathVariable Long id) {
    return examPaperService.detail(id); // 内部查询后直接 return
}

3. 为什么会报错?

经过查阅资料得知(文末有链接),Jackson 2.x 默认不带 JSR-310 模块(java.time.*),于是序列化 LocalDateTime 时直接蒙圈。
Spring Boot 2.7+ 已帮你依赖了 jackson-datatype-jsr310,但没有自动注册为模块,需要手动或配置开启。


4. 四种解决方案

方案场景侵入性备注
A. 直接注解仅个别字段最低最常用
B. 全局配置全项目统一推荐
C. 手动注册模块非 Spring通用
D. 自定义序列化器个性格式最灵活

✅ 方案 A:字段级注解(最快)

@Data
public class ExamPaperVO {
    private Long id;
    private String title;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @JsonSerialize(using = LocalDateTimeSerializer.class)
    private LocalDateTime generateTime;
}

优点:零配置,随改随生效
缺点:每个字段都要写,重复劳动


✅ 方案 B:Spring Boot 全局配置(推荐)

Maven 依赖(Spring Boot 2.7+ 已自带,可跳过)
<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
配置类
@Configuration
public class JacksonConfig {

    @Bean
    public Jackson2ObjectMapperBuilderCustomizer customizer() {
        return builder -> {
            // 统一格式
            builder.serializerByType(LocalDateTime.class,
                    new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            builder.deserializerByType(LocalDateTime.class,
                    new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            // 关闭时间戳
            builder.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        };
    }
}

优点:一次配置,全项目生效
缺点:Spring Boot 专属


✅ 方案 C:手动注册模块(纯 Jackson)

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule()); // 关键
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

适用于非 Spring 环境(如 Vert.x、Quarkus、普通 JavaSE)。


✅ 方案 D:自定义序列化器(复杂格式)

public class CustomLocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {

    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm");

    @Override
    public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers)
            throws IOException {
        gen.writeString(value.format(FORMATTER));
    }
}

// 使用
@JsonSerialize(using = CustomLocalDateTimeSerializer.class)
private LocalDateTime generateTime;

5. 一键复制版补丁(Spring Boot)

<!-- pom.xml 已自带可省 -->
<!-- application.yml -->
spring:
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8
    serialization:
      write-dates-as-timestamps: false

6. 小结

场景推荐方案
只想快速修复单个字段方案 A
新项目/统一风格方案 B
非 Spring 框架方案 C
日期格式极度个性化方案 D

7. 参考资料

如果本文帮到你,记得点赞收藏!评论区一起交流更多 Jackson 坑位~

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Neoest

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值