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

OffsetDateTime序列化与反序列化结果不一致原因及解决方案咨询

问题根因
  1. Jackson默认时区转换逻辑:Jackson默认开启了DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE配置,反序列化日期时会自动将时间调整到Jackson上下文配置的时区(Spring Boot默认上下文时区为UTC,标识为Z)。你接口返回的原始值2021-10-21T23:59:59.999999999-18:00转换为UTC时间后刚好是2021-10-22T17:59:59.999999999Z,所以日期会跨天、时区标识变成Z。
  2. OffsetDateTime的equals规则:OffsetDateTime的equals方法不仅会比较时间对应的瞬时点,还会严格比较时区偏移量,即使两个对象代表同一个全球瞬时时间,只要偏移量不同,equals就会返回false。你构造预期对象时用LocalDate.atTime(OffsetTime.MAX)得到的偏移量是-18:00,和反序列化得到的UTC偏移量+00:00不一致,所以校验失败。
修复方案

可根据业务需求选择任意一种方案:

  • 方案1:关闭Jackson自动时区调整(保留原始偏移量)
    在你现有的Jackson2ObjectMapperBuilderCustomizer配置中添加禁用自动时区调整的配置:
@Bean
public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer(CustomAnnotationIntrospector customAnnotationIntrospector) {
    return builder -> builder.serializationInclusion(NON_NULL)
        .annotationIntrospector(customAnnotationIntrospector)
        // 新增下面这行,关闭反序列化自动调整到上下文时区
        .featuresToDisable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
}

改完后反序列化会保留原始响应里的-18:00偏移量,和你构造的预期对象完全一致,equals校验即可通过。

  • 方案2:统一使用UTC时区(业务需要统一时区的场景)
    构造预期对象时将时间转换为UTC时区的OffsetDateTime,和反序列化后的时区保持一致:
private Request getExpectedRequest() {
    LocalDate date = LocalDate.of(2021, Month.OCTOBER, 22);
    OffsetDateTime dateTime = date.atTime(OffsetTime.MAX)
        // 转换为同一瞬时的UTC时间
        .atZoneSameInstant(ZoneOffset.UTC)
        .toOffsetDateTime();
    return new Request(dateTime);
}
  • 方案3:仅校验瞬时时间是否一致(不关心偏移量的场景)
    不要直接比较整个Request对象,单独比较日期的瞬时时间点:
// 把原来的assertEquals替换成下面的逻辑
Request actual = mapToObject(result.getResponse().getContentAsString(StandardCharsets.UTF_8), Request.class);
Request expected = getExpectedRequest();
Assertions.assertEquals(expected.getDate().toInstant(), actual.getDate().toInstant());
// 其他字段正常校验...

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 01:45:03