You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot中Jackson处理java.time.Duration序列化失败求助

解决Spring REST服务中Duration序列化/反序列化的错误问题

看起来你遇到的是Jackson对Java 8 Duration类型处理不当导致的反序列化错误。咱们一步步来搞定这个问题:

错误原因分析

你当前的请求体用的是Jackson内部对Duration的表示结构(包含seconds、nano、units字段),但Spring默认的Jackson配置(如果没引入JSR310模块)或者默认序列化规则,并不认识这种结构——它期望的是符合ISO-8601标准的Duration字符串(比如PT1H30M),所以才会抛出"Failed to read H..."这类反序列化失败的错误。

解决方案

1. 引入Jackson的Java 8时间模块

首先,确保项目依赖里包含Jackson对Java 8日期时间类型的支持模块,因为Duration属于Java 8新增的时间API:

如果是Maven项目,在pom.xml里添加:

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
    <!-- 版本建议和项目中Jackson核心版本保持一致 -->
    <version>2.15.2</version>
</dependency>

Gradle项目的话:

implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.2'

2. 配置Jackson正确处理Duration

接下来需要让Jackson把Duration序列化为ISO格式字符串,同时也能从ISO字符串反序列化。有两种实现方式:

方式一:全局配置(推荐)

创建Jackson配置类,让配置全局生效:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class JacksonTimeConfig {
    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        // 注册Java 8时间模块
        objectMapper.registerModule(new JavaTimeModule());
        // 禁用将Duration序列化为时间戳,改用ISO格式字符串
        objectMapper.disable(com.fasterxml.jackson.databind.SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS);
        return objectMapper;
    }
}

方式二:字段级注解配置

如果只想针对A类里的availTime字段生效,可以在字段上添加注解:

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.deser.DurationDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.DurationSerializer;
import java.time.Duration;

public class A {
    @JsonSerialize(using = DurationSerializer.class)
    @JsonDeserialize(using = DurationDeserializer.class)
    private Duration availTime;

    // 别忘了添加getter和setter方法
    public Duration getAvailTime() {
        return availTime;
    }

    public void setAvailTime(Duration availTime) {
        this.availTime = availTime;
    }
}

3. 修改请求体为标准ISO格式

现在你需要把请求体改成符合ISO-8601的Duration字符串,替换原来的内部结构:

{ "availTime": "PT1H30M" }

这样Spring就能正确反序列化请求体,同时响应也会返回你期望的{"availTime": "PT1H30M"}格式。

补充说明

Jackson的JavaTimeModule默认基于ISO标准字符串处理Duration,你之前传的包含seconds、nano的结构是Jackson内部的非标准序列化格式,不是REST服务交互的推荐格式,所以更建议使用标准ISO字符串来传递Duration数据。

内容的提问来源于stack exchange,提问作者Chris Antonopoulos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:33:14