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

Spring Boot 3中ObjectMapper反序列化List<Map>到DTO时Instant字段报错

解决Spring Boot 3升级后Instant反序列化异常问题

问题原因

Spring Boot 3升级后,底层JdbcTemplate对数据库datetimeoffset类型的处理逻辑发生变化:

  • Spring Boot 2中,该类型会被转为字符串返回
  • Spring Boot 3中,默认转为OffsetDateTime对象返回

当你用ObjectMapper将List<Map<String,Object>>转换为DTO时,原本期望字符串转Instant,但实际是OffsetDateTime对象转Instant,Jackson默认没有对应的转换器,因此抛出Cannot deserialize value of type java.time.Instant from Object value异常。

解决方案

方案1:修改DTO字段类型(推荐,贴合数据模型)

数据库datetimeoffset带时区信息,Java中OffsetDateTime是最匹配的类型,直接替换DTO中的Instant:

public class DTO {
    // 其他字段保持不变
    private OffsetDateTime createdDate;
    private OffsetDateTime lastModifiedDate;

    // 如需对外提供Instant类型,可添加转换方法
    public Instant getCreatedDateAsInstant() {
        return createdDate != null ? createdDate.toInstant() : null;
    }

    public Instant getLastModifiedDateAsInstant() {
        return lastModifiedDate != null ? lastModifiedDate.toInstant() : null;
    }

    // getter、setter、构造方法不变
}

此方案无需额外配置,ObjectMapper可直接完成赋值。

方案2:配置ObjectMapper支持类型转换

若不想修改DTO,可自定义ObjectMapper,添加OffsetDateTime到Instant的转换器:

@Configuration
public class JacksonConfig {
    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        JavaTimeModule timeModule = new JavaTimeModule();

        // 注册OffsetDateTime转Instant的转换器
        timeModule.addConverter(new Converter<OffsetDateTime, Instant>() {
            @Override
            public Instant convert(OffsetDateTime source) {
                return source != null ? source.toInstant() : null;
            }
        });

        objectMapper.registerModule(timeModule);
        // 禁用日期序列化时间戳,统一用字符串格式
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        return objectMapper;
    }
}

方案3:修改SQL查询,返回字符串格式日期

在查询SQL中,将datetimeoffset字段转换为ISO标准字符串,确保Map中对应值为字符串类型:
以SQL Server为例:

SELECT
    loanId,
    obligor,
    -- 转换为ISO 8601格式字符串
    CONVERT(varchar(50), lastModifiedDate, 127) AS lastModifiedDate,
    CONVERT(varchar(50), createdDate, 127) AS createdDate,
    -- 其他字段...
FROM your_target_table

转换后的字符串格式为2024-05-09T15:46:30.199154Z,Jackson可直接反序列化为Instant。

内容的提问来源于stack exchange,提问作者aakash singh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 08:57:35