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

Spring接口如何将JSON中yyyyMMdd日期字符串转为OffsetDateTime

问题原因
  • 默认反序列化得到1970年错误时间:未匹配到对应字符串解析规则时,Jackson会将纯数字格式的日期字符串尝试转换为时间戳数值,20200716被当作自1970-01-01起的时间量计算,最终得到不符合预期的时间结果。
  • 直接添加@JsonFormat("yyyyMMdd")报错:OffsetDateTime类型解析必须包含时间、时区偏移字段信息,仅指定日期格式yyyyMMdd时,解析器缺失必要字段的赋值规则,无法完成转换。
解决方案

根据业务影响范围选择对应方案即可:

方案1:单字段自定义解析(推荐,无全局侵入)

仅对birthDate字段生效,不影响项目中其他OffsetDateTime字段的解析逻辑,最适配单字段特殊格式的场景。

  1. 修正字段注解,指定JSON字段名与自定义反序列化器:
public class UserRequest {
    // 其他字段...
    @JsonProperty("birth-date")
    @JsonDeserialize(using = YyyyMMddOffsetDateTimeDeserializer.class)
    private OffsetDateTime birthDate;
    // getter/setter...
}
  1. 实现自定义反序列化器,解析时自动补全0点时间与UTC+0偏移量:
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import java.io.IOException;
import java.time.LocalDate;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;

public class YyyyMMddOffsetDateTimeDeserializer extends JsonDeserializer<OffsetDateTime> {
    private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("yyyyMMdd");

    @Override
    public OffsetDateTime deserialize(JsonParser parser, DeserializationContext context) throws IOException {
        String dateValue = parser.getText().trim();
        LocalDate parseDate = LocalDate.parse(dateValue, DATE_FORMAT);
        // 时间置为00:00:00,时区偏移置为UTC+0,符合预期格式
        return parseDate.atStartOfDay().atOffset(ZoneOffset.UTC);
    }
}

方案2:全局统一配置(适用于全项目统一格式场景)

如果项目中所有OffsetDateTime类型的入参都需要兼容yyyyMMdd格式的纯日期字符串,可直接配置Jackson全局规则,无需在每个字段上加注解。

import com.fasterxml.jackson.datatype.jsr310.deser.OffsetDateTimeDeserializer;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;

@Configuration
public class JacksonDateConfig {
    @Bean
    public Jackson2ObjectMapperBuilderCustomizer offsetDateTimeCustomizer() {
        // 为缺失的时间、时区字段配置默认值
        DateTimeFormatter formatter = new DateTimeFormatterBuilder()
                .appendPattern("yyyyMMdd")
                .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
                .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
                .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
                .parseDefaulting(ChronoField.NANO_OF_SECOND, 0)
                .parseDefaulting(ChronoField.OFFSET_SECONDS, ZoneOffset.UTC.getTotalSeconds())
                .toFormatter();

        return builder -> builder.deserializerByType(OffsetDateTime.class, new OffsetDateTimeDeserializer(formatter));
    }
}

注意:Spring Boot 2.x及以上版本默认已集成jackson-datatype-jsr310依赖,无需额外引入;如果是1.x版本需手动引入该依赖,并确保spring.jackson.serialization.write-dates-as-timestamps配置为false,避免日期被序列化为时间戳格式。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 17:30:46