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




