Spring Boot 2.5.0 和 InvalidDefinitionException:默认情况下不支持 Java 8 日期/时间类型 `java.time.Instant`

ale*_*oid 17 java spring jackson spring-boot

从 Spring Boot 2.4.5 更新到 Spring 2.5.0 后,我注意到应用程序日志中存在以下异常:

Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Java 8 date/time type `java.time.Instant` not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling (through reference chain: org.telegram.telegrambots.meta.api.objects.Update["my_chat_member"]->org.telegram.telegrambots.meta.api.objects.ChatMemberUpdated["new_chat_member"]->org.telegram.telegrambots.meta.api.objects.ChatMember["untilDateAsInstant"])
    at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77) ~[jackson-databind-2.12.3.jar!/:2.12.3]
    at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1276) ~[jackson-databind-2.12.3.jar!/:2.12.3]
    at com.fasterxml.jackson.databind.ser.impl.UnsupportedTypeSerializer.serialize(UnsupportedTypeSerializer.java:35) ~[jackson-databind-2.12.3.jar!/:2.12.3]
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728) ~[jackson-databind-2.12.3.jar!/:2.12.3]
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:770) ~[jackson-databind-2.12.3.jar!/:2.12.3]
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178) ~[jackson-databind-2.12.3.jar!/:2.12.3]
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728) ~[jackson-databind-2.12.3.jar!/:2.12.3]
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:770) ~[jackson-databind-2.12.3.jar!/:2.12.3]
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178) ~[jackson-databind-2.12.3.jar!/:2.12.3]
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728) ~[jackson-databind-2.12.3.jar!/:2.12.3]
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:770) ~[jackson-databind-2.12.3.jar!/:2.12.3]
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178) ~[jackson-databind-2.12.3.jar!/:2.12.3]
    at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480) ~[jackson-databind-2.12.3.jar!/:2.12.3]
    at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319) ~[jackson-databind-2.12.3.jar!/:2.12.3]
    at com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1514) ~[jackson-databind-2.12.3.jar!/:2.12.3]
    at com.fasterxml.jackson.databind.ObjectWriter._writeValueAndClose(ObjectWriter.java:1215) ~[jackson-databind-2.12.3.jar!/:2.12.3]
    at com.fasterxml.jackson.databind.ObjectWriter.writeValue(ObjectWriter.java:1059) ~[jackson-databind-2.12.3.jar!/:2.12.3]
    at org.springframework.jms.support.converter.MappingJackson2MessageConverter.mapToTextMessage(MappingJackson2MessageConverter.java:279) ~[spring-jms-5.3.7.jar!/:5.3.7]
    at org.springframework.jms.support.converter.MappingJackson2MessageConverter.toMessage(MappingJackson2MessageConverter.java:184) ~[spring-jms-5.3.7.jar!/:5.3.7]
    ... 37 common frames omitted
Run Code Online (Sandbox Code Playgroud)

这是我的 pom.xml:

    <dependency>
        <groupId>com.fasterxml.jackson.datatype</groupId>
        <artifactId>jackson-datatype-jsr310</artifactId>
    </dependency>

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
    </dependency>
Run Code Online (Sandbox Code Playgroud)

我恢复到 Spring Boot 2.4.5,但并非一切正常。Spring Boot 2.5.0 可能有什么问题?

更新

对应的GitHub https://github.com/spring-projects/spring-boot/issues/26859

Sai*_*ant 36

我在我的一个测试课程中发现了一个问题。问题在于创建一个新的 ObjectMapper 实例,但没有添加 JavaTimeModule。

这是一个在 Spring 2.4.5 中有效但在 2.5.0/2.5.1 中失败的示例测试,并出现 com.fasterxml.jackson.databind.exc.InvalidDefinitionException:java.time.ZonedDateTime默认情况下不支持Java 8 日期/时间类型

可能是由于jackson-datatype-jsr310版本升级所致

package net.jpmchase.gti.gtfabric;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;

import java.time.ZonedDateTime;

public class ObjectMapperTest {

    @Test
    public void objectMapperTest() throws Exception{

        ZonedDateTime time = ZonedDateTime.now();
        ObjectMapper o = new ObjectMapper();
        o.writeValueAsString(time);
    }
}
Run Code Online (Sandbox Code Playgroud)

要修复这个特定的测试用例必须添加一个显式的

ObjectMapper o = new ObjectMapper();
o.registerModule(new JavaTimeModule()); 
Run Code Online (Sandbox Code Playgroud)

  • 这不是一个答案,只是告诉您如何重现该问题。如果您的依赖项使用 ObjectMapper,则没有帮助。没有什么可以阻止 spring 拾取损坏的 ObjectMapper。 (3认同)
  • 我在单元测试中评估值时遇到了这个问题,这解决了它执行 ```new ObjectMapper().registerModule(new JavaTimeModule()).writeValueAsString(value);``` :D 谢谢 (2认同)

Daw*_*ski 11

也许您没有在代码中使用spring提供的Object Mapper。

错误的方法:

ObjectMapper o = new ObjectMapper();
Run Code Online (Sandbox Code Playgroud)

正确方法:

@Autowired
Jackson2ObjectMapperBuilder mapperBuilder;
Run Code Online (Sandbox Code Playgroud)

...

ObjectMapper mapper = mapperBuilder.build();
Run Code Online (Sandbox Code Playgroud)