一. 報(bào)錯(cuò)信息
最近新開了一個(gè)測試項(xiàng)目,使用了Java8的LocalDateTime替換了之前使用的Date類。接口返回結(jié)果時(shí),拋出了序列化異常:
java.lang.reflect.UndeclaredThrowableException: null
…………
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Java 8 date/time type `java.time.LocalDateTime` not supported by default:
add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling (through reference chain:
cn.xx.dao.common.Back["data"]->cn.xx.dao.data.vo.BmVo["spe"]->
cn.xx.dao.entity.Spe["createTime"])
二. 版本信息
spring boot:2.5.1
jackson-databind:2.12.3
……
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
……
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.3</version>
<scope>compile</scope>
</dependency>
</dependencies>
三. 解決方法
1. 使用@JsonSerialize + @JsonDeserialize注解
- pom加上這兩個(gè)注解的依賴
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.12.3</version>
</dependency>
- 在使用LocalDateTime的屬性上添加這兩個(gè)序列化反序列化注解:
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
private LocalDateTime createTime;
這時(shí)序列化正常,接口返回了結(jié)果,但是很明顯不是我們需要的結(jié)果:
{
"createTime": [
2023,
3,
20,
17,
34,
37
]
}
- 加上@JsonFormat來格式化時(shí)間,現(xiàn)在就可以正常輸出了:
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
private LocalDateTime createTime;
InvalidDefinitionException這個(gè)報(bào)錯(cuò),大部分博客提供的思路都是這個(gè),理論上沒什么問題,但是實(shí)際情況可能需要全局處理如LocalDateTime的時(shí)間格式,如果為相關(guān)的時(shí)間字段一個(gè)個(gè)的加注解,又太過麻煩。所以這種方法只能用于需要處理特定時(shí)間格式的字段上。
2. 回退Spring Boot版本
鑒于方法A只能作用于局部,而使用Jackson2ObjectMapperBuilderCustomizer時(shí),仍然無法解決InvalidDefinitionException這個(gè)異常問題,只能將Spring Boot回退至2.4.x版本,問題得到解決。
參考:Spring Boot 2.5.0 and InvalidDefinitionException: Java 8 date/time type java.time.Instant not supported by default
解決流程:
- 設(shè)置Jackson2ObjectMapperBuilderCustomizer:
@Configuration
public class GlobalDateConfig {
// 序列化時(shí)設(shè)置的時(shí)間格式
private final String formatter = "yyyy-MM-dd HH:mm:ss";
@Bean
public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
return builder -> {
DateTimeFormatter localDateTimeFormatter = DateTimeFormatter.ofPattern(formatter);
//返回時(shí)間數(shù)據(jù)序列化
builder.serializerByType(LocalDateTime.class, new LocalDateTimeSerializer(localDateTimeFormatter));
// 接收時(shí)間數(shù)據(jù)反序列化
builder.deserializerByType(LocalDateTime.class, new LocalDateTimeDeserializer(localDateTimeFormatter));
};
}
}
- 回退Spring Boot版本至2.4.x
……
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
……
- 重啟執(zhí)行,問題解決
3. 回退jackson版本
Spring Boot 2.4.x使用的是jackson 2.11.x
Spring Boot 2.5.x使用的是jackson 2.12.x
參考:Spring Boot 2.5.0 and InvalidDefinitionException: Java 8 date/time type java.time.Instant not supported by default
- 無須修改Spring Boot版本,并顯式的指定jackson版本(2.13也報(bào)這個(gè)錯(cuò)誤,原因可以參考這里:a change in Jackson 2.12、comment of 2.4 and 2.5)
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.11.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.11.2</version>
</dependency>
- 使用上文的GlobalDateConfig配置,重啟執(zhí)行,問題解決
四. 一些嘗試(未解決問題)
根據(jù)Spring Boot的討論和Stack overflow的一些解決方法做了一些嘗試,但是均未成功解決問題。
1. 向自定義ObjectMapper Bean中注冊JavaTimeModule
我的項(xiàng)目中,并不存在這種自定義ObjectMapper且將其設(shè)置為全局Bean的情況。
如果存在自定義ObjectMapper Bean的情況下,需要注冊處理java8時(shí)間序列化的類:JavaTimeModule(或者Jdk8Module)
@Bean
@Primary
public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
return objectMapper;
}
或者:
@Bean
@Primary
public ObjectMapper objectMapper() {
return JsonMapper.builder()
.addModule(new JavaTimeModule())
.build();
}
或者
@Resource
private Jackson2ObjectMapperBuilder mapperBuilder;
@Bean
@Primary
public ObjectMapper objectMapper() {
ObjectMapper build = mapperBuilder.build();
objectMapper.registerModule(new JavaTimeModule());
return objectMapper;
}
這幾種情況沒遇到過,不知道是否可行??傊@里對我的代碼不起作用。
此外,JavaTimeModule還支持自定義格式
DateTimeFormatter localDateTimeFormatter = DateTimeFormatter.ofPattern(formatter);
// 添加Java8時(shí)間序列化反序列化
JavaTimeModule javaTimeModule = new JavaTimeModule();
//返回時(shí)間數(shù)據(jù)序列化
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(localDateTimeFormatter));
//接收時(shí)間數(shù)據(jù)反序列化
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(localDateTimeFormatter));
2. 設(shè)置Jackson2ObjectMapperBuilder類
- 設(shè)置Jackson2ObjectMapperBuilder類,控制序列化和反序列化操作。
很明顯,這個(gè)就是實(shí)現(xiàn)一個(gè)Jackson2ObjectMapperBuilderCustomizer類,與上文中的方法jackson2ObjectMapperBuilderCustomizer作用相同。這里也無法解決開頭的問題。
@Configuration
public class GlobalDateConfig implements Jackson2ObjectMapperBuilderCustomizer {
private final String formatter = "yyyy-MM-dd HH:mm:ss";
@Override
public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
jacksonObjectMapperBuilder.simpleDateFormat(formatter)
.modules(new JavaTimeModule())
.serializationInclusion(JsonInclude.Include.ALWAYS)
.failOnEmptyBeans(false)
.failOnUnknownProperties(false)
.featuresToEnable(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN)
.featuresToEnable(JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS);
}
}
文章來源:http://www.zghlxwxcb.cn/news/detail-560938.html
參考
Spring Boot 2.5.0 and InvalidDefinitionException: Java 8 date/time type java.time.Instant not supported by default
文章來源地址http://www.zghlxwxcb.cn/news/detail-560938.html
到了這里,關(guān)于解決報(bào)錯(cuò)InvalidDefinitionException Java 8 date/time type LocalDateTime not supported by default jsr310的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!