是否有任何选项可以在 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 应用程序中使浏览器缓存无效