是否有任何选项可以在 Spring Boot 中使用 Jackson 为 java.time.* 包注册一次 Serializer/Deserializer?

Posted

技术标签:

【中文标题】是否有任何选项可以在 Spring Boot 中使用 Jackson 为 java.time.* 包注册一次 Serializer/Deserializer?【英文标题】:Is there any option to register Serializer/Deserializer only once for java.time.* packages using Jackson in Spring Boot? 【发布时间】:2021-02-18 01:05:56 【问题描述】:

团队您好,

我正在开发一个 Spring Boot 项目(版本 2.3.4 发行版),其中我使用 java.time.LocalDate、java.time.LocalDateTime 和 java.time.LocalTime 数据类型来处理几个 bean 中的一些属性。

但是,这些字段不会自动反序列化,除非我明确地向它们提供以下注释以及我的自定义反序列化器。

@JsonFormat(pattern="dd-MMM-yyyy")
@JsonDeserialize(using= LocalDateWithStringsDeserializer.class)
private LocalDate date_of_joining;

将这些注释添加到所有 bean 中确实是一项耗时的工作,因为该项目中有超过 400-500 个 bean。

如果未提供这些注释,则会出现以下错误。

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `java.time.LocalDate` (no Creators, like default construct, exist): no String-argument constructor/factory method to deserialize from String value ('27-May-1999')

我还尝试定义一个显式 Bean 以使用我的自定义反序列化器覆盖 Spring Boot objectmapper,但这甚至没有帮助我。相同的代码sn-p如下所述。

@Bean
@Primary
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) 
    ObjectMapper objectMapper = builder.build();
    objectMapper.findAndRegisterModules();
    objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    objectMapper.setDateFormat(dateformat);
    SimpleModule module = new SimpleModule();
    module.addDeserializer(LocalDateTime.class, new MillisOrLocalDateTimeDeserializer());
    module.addDeserializer(LocalDate.class, new LocalDateWithStringsDeserializer());
    module.addDeserializer(LocalTime.class, new LocalTimeWithStringDeserializer());
    objectMapper.registerModule(module);
    return objectMapper;

我什至在我的项目中的 pom.xml 文件中添加了以下依赖项。

    <dependency>
        <groupId>com.fasterxml.jackson.datatype</groupId>
        <artifactId>jackson-datatype-jsr310</artifactId>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.module</groupId>
        <artifactId>jackson-module-parameter-names</artifactId>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.datatype</groupId>
        <artifactId>jackson-datatype-jdk8</artifactId>
    </dependency>
    <dependency>
        <groupId>javax.xml.bind</groupId>
        <artifactId>jaxb-api</artifactId>
    </dependency>

请提出解决方案。

【问题讨论】:

开箱即用,但默认情况下它支持 ISO 格式。您没有以 ISO 格式发送日期,因此解析失败。所以要么以 ISO 格式发送日期,要么更改要使用的模式。 实际上,我从其他 API 调用收到的反序列化响应没有 ISO 格式的日期。但是,我在注释 @JsonFormat(pattern="dd-MMM-yyyy") 中指定了模式,但不想每次都向每个 bean 添加此类注释。 您可以设置(反)序列化程序的属性。 spring.jackson.date-format 默认为 ISO(这在 Spring Boot 文档中都提到了,我建议您可能想略读一下)。 我已将属性 spring.jackson.date-format=dd-MMM-yyyy 添加到我的应用程序的属性文件中,但我仍然收到以下错误。 com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of java.time.LocalDate (no Creators, like default construct, exist): no String-argument constructor/factory method to deserialize from String value ('27-May-1999') 请提出解决方案。 您还应该删除您拥有的注释和明确配置的ObjectMapper,否则它将不会被应用。 【参考方案1】:

所以我想出了解决方案。之前配置的其他一些对象映射器在项目中使用 Joda Time,这些映射器已作为必需库添加到我的项目的构建路径中。

修改现有对象映射器并在该项目中为日期和时间注册 Java 时间模块和自定义反序列化器,就像我在这个问题中提到的那样解决了这个问题。

【讨论】:

以上是关于是否有任何选项可以在 Spring Boot 中使用 Jackson 为 java.time.* 包注册一次 Serializer/Deserializer?的主要内容,如果未能解决你的问题,请参考以下文章

是否可以为 Spring Boot 应用程序提供 oauth 和基本用户名密码登录选项?

如何在使用 Angular 7 和 Spring Boot 构建的 Web 应用程序中使浏览器缓存无效

Kotlin Spring Boot CORS“选项/用户没有映射”

在 Spring Boot 中读取环境变量

Spring Boot - 日志记录

Spring-Boot 仅在一个配置文件中执行 data.sql