You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Spring Boot集成Jackson 310时LocalDateTime反序列化失败求助

解决Spring Boot + Jackson 3.x 无法反序列化LocalDateTime的问题

这个问题我之前也碰到过,Jackson 3.x 默认不支持Java 8引入的LocalDateTime这类新时间API,再加上注解配置不当的话,就会出现各种解析失败的情况。我给你几个可行的解决方案,一步步来排查:

1. 确认依赖是否正确(Spring Boot场景)

Spring Boot的spring-boot-starter-web其实已经内置了jackson-datatype-jsr310模块(专门支持Java 8时间API的Jackson扩展包),但如果是单独引入Jackson或者存在版本冲突,可能需要手动添加依赖:

<!-- Maven依赖,版本对应你的Jackson 3.10.x -->
<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
    <version>3.10.x</version>
</dependency>

2. 修正DTO中的@JsonFormat注解

你当前使用的shape = JsonFormat.Shape.ANY会让Jackson尝试多种类型解析,反而容易出错。改成Shape.STRING明确告知Jackson这是字符串格式的时间:

@ApiModel
@Validated
public class DateRange implements Serializable {
    @ApiModelProperty
    @NotNull
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT")
    protected LocalDateTime start;

    @ApiModelProperty
    @NotNull
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT")
    protected LocalDateTime end;
    // 其他代码...
}

如果需要支持带T的格式(比如2017-05-04T11:28:56.816),只需要把pattern改成对应的格式即可:

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS", timezone = "GMT")

3. 全局配置Jackson支持LocalDateTime(推荐)

如果不想每个时间字段都单独加注解,可以全局配置Jackson,让它默认支持LocalDateTime的序列化和反序列化,还能同时兼容多种时间格式:

方式1:通过application.yml配置

spring:
  jackson:
    serialization:
      write-dates-as-timestamps: false # 禁用时间戳格式,强制用字符串输出
    deserialization:
      adjust-dates-to-context-time-zone: false # 禁止自动调整时区
    time-zone: GMT # 统一指定时区
    date-format: yyyy-MM-dd HH:mm:ss # 默认解析/生成的时间格式

方式2:自定义Jackson配置类(支持多格式解析)

如果需要同时兼容带T和不带T的多种时间格式,可以写一个配置类注册自定义反序列化器:

@Configuration
public class JacksonConfig {

    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        JavaTimeModule javaTimeModule = new JavaTimeModule();

        // 注册支持多种格式的LocalDateTime反序列化器
        javaTimeModule.addDeserializer(LocalDateTime.class, new MultiFormatLocalDateTimeDeserializer());
        objectMapper.registerModule(javaTimeModule);

        // 禁用时间戳序列化
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        return objectMapper;
    }

    // 自定义多格式反序列化器
    static class MultiFormatLocalDateTimeDeserializer extends LocalDateTimeDeserializer {
        private static final List<DateTimeFormatter> FORMATTERS = Arrays.asList(
                DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"),
                DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"),
                DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS")
        );

        public MultiFormatLocalDateTimeDeserializer() {
            super(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
        }

        @Override
        public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
            String timeStr = p.getText().trim();
            // 依次尝试多种格式解析
            for (DateTimeFormatter formatter : FORMATTERS) {
                try {
                    return LocalDateTime.parse(timeStr, formatter);
                } catch (DateTimeParseException ignored) {
                    // 格式不匹配,继续尝试下一个
                }
            }
            throw new IOException("无法解析时间字符串: " + timeStr);
        }
    }
}

4. 排查时区问题

你配置了timezone = "GMT",要确保前端传递的时间确实是GMT时区的。如果前端传的是东八区时间(比如北京时间),需要把时区改成"Asia/Shanghai",否则会出现时间偏移的问题。


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

火山引擎 最新活动