Spring Boot LocalDate 字段序列化和反序列化

Posted

技术标签:

【中文标题】Spring Boot LocalDate 字段序列化和反序列化【英文标题】:Spring Boot LocalDate field serialization and deserialization 【发布时间】:2015-09-01 11:43:28 【问题描述】:

在 Spring Boot 1.2.3.RELEASE 中使用 fasterxml 将LocalDate 字段序列化和反序列化为 ISO 日期格式字符串的正确方法是什么?

我试过了:

spring.jackson.serialization.write-dates-as-timestamps:false 在 application.properties 文件中,

在项目中包含jackson-datatype-jsr310,然后使用

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")注解

@DateTimeFormat(iso=ISO.DATE)注解,

Jsr310DateTimeFormatAnnotationFormatterFactory 添加为格式化程序:

@Override
public void addFormatters(FormatterRegistry registry) 
    registry.addFormatterForFieldAnnotation(new Jsr310DateTimeFormatAnnotationFormatterFactory());

以上都没有帮助。

【问题讨论】:

【参考方案1】:
compile ("com.fasterxml.jackson.datatype:jackson-datatype-jsr310")

在 build.gradle 中 然后以下注释有所帮助:

@JsonDeserialize(using = LocalDateDeserializer.class)
@JsonSerialize(using = LocalDateSerializer.class)
private LocalDate birthday;

更新:如果您使用的是 Spring Boot 2.*,则依赖项已通过“启动器”之一包含在内。

【讨论】:

这为我解决了问题。升级使用spring boot 1.3.0.BUILD.SNAPSHOT版本时遇到反序列化问题。 你能指定你的解决方案吗? 是的,您需要 com.fasterxml.jackson.datatype:jackson-datatype-jsr310 依赖项,然后您可以将 @JsonDeserialize @JsonSerialize 注释与 LocalDate 字段一起使用,就像答案中一样。 在 SpringBoot 1.3.6.RELEASE 上对我不起作用;/ 出现错误:com.fasterxml.jackson.datatype.jsr310.ser.JSR310FormattedSerializerBase.findFormatOverrides(Lcom/fasterxml/jackson/databind/SerializerProvider;Lcom/fasterxml/jackson/databind/BeanProperty;Ljava/lang/Class;)Lcom/fasterxml/jackson/annotation/JsonFormat$Value; 解决了我的问题。使用 LocalDateTime 杰克逊反序列化,谢谢【参考方案2】:

在我的 Spring Boot 2 应用程序中

@JsonFormat 注解在(反)序列化 JSON 数据时在 REST 控制器中使用。 @DateTimeFormat 注解在其他控制器中使用 ModelAttributes 在(反)序列化字符串数据时。

您可以在同一个字段上指定两者(如果您在 JSON 和 Thymeleaf 模板之间共享 DTO,这很有用):

@JsonFormat(pattern = "dd/MM/yyyy") 
@DateTimeFormat(pattern = "dd/MM/yyyy")
private LocalDate birthdate;

Gradle 依赖:

implementation group: 'org.springframework.boot', name: 'spring-boot-starter-json'

我希望这是您在 Spring Boot 2.x 应用程序中自定义日期/时间格式所需的所有配置。


对于 Spring Boot 1.x 应用,指定额外的注解和依赖:

@JsonFormat(pattern = "dd/MM/yyyy")
@DateTimeFormat(pattern = "dd/MM/yyyy")
@JsonDeserialize(using = LocalDateDeserializer.class)
@JsonSerialize(using = LocalDateSerializer.class)
private LocalDate birthDate;

// or
@JsonFormat(pattern = "dd/MM/yyyy HH:mm")
@DateTimeFormat(pattern = "dd/MM/yyyy HH:mm")
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JsonSerialize(using = LocalDateTimeSerializer.class)
private LocalDateTime birthDateTime;
implementation group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-jsr310', version: '2.9.8'

请注意,如果有人以错误的格式发送日期,您的 API 将抛出“JSON 解析错误”。映射示例:

@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate releaseDate;

异常示例:

HttpMessageNotReadableException:JSON 解析错误:无法从字符串“2002”反序列化 java.time.LocalDate 类型的值:无法反序列化 java.time.LocalDate:(java.time.format.DateTimeParseException)无法在索引 4 处解析文本“2002”;嵌套异常是com.fasterxml.jackson.databind.exc.InvalidFormatException:无法从字符串“2002”反序列化java.time.LocalDate 类型的值:无法反序列化java.time.LocalDate:(java.time.format.DateTimeParseException)无法在索引4 处解析文本“2002”

【讨论】:

【参考方案3】:

如果您想使用自定义 Java 日期格式化程序,请添加 @JsonFormat 注释。

@JsonFormat(pattern = "dd/MM/yyyy")
@JsonDeserialize(using = LocalDateDeserializer.class)
@JsonSerialize(using = LocalDateSerializer.class)
private LocalDate birthdate;*

【讨论】:

【参考方案4】:

其实只要在 pom.xml 中指定依赖就可以了。

这样,我所有的 LocalDate 字段都会自动使用 ISO 格式,无需注释:

<!-- This is enough for LocalDate to be deserialized using ISO format -->
<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
</dependency>

在 Spring Boot 1.5.7 上测试。

【讨论】:

【参考方案5】:
 @Bean
public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() 
    return builder -> 
        DateTimeFormatter localDateFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
        builder.serializerByType(LocalDate.class, new LocalDateSerializer(localDateFormatter));
        builder.deserializerByType(LocalDate.class, new LocalDateDeserializer(localDateFormatter));

        DateTimeFormatter localDateTimeFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
        builder.serializerByType(LocalDateTime.class, new LocalDateTimeSerializer(localDateTimeFormatter));
        builder.deserializerByType(LocalDateTime.class, new LocalDateTimeDeserializer(localDateTimeFormatter));
    ;

【讨论】:

以上是关于Spring Boot LocalDate 字段序列化和反序列化的主要内容,如果未能解决你的问题,请参考以下文章

使用 Spring Boot 2 和 Kotlin 进行 Jackson 反序列化,无法构造 `java.time.LocalDate` 的实例

如何在 Spring Boot 中为 Camel 配置 Jackson ObjectMapper

Gson 没有正确序列化 LocalDate

无法使用 Jackson 将 java.time.LocalDate 序列化为字符串

mybatis-plus 中的LocalDateTime, LocalDate, LocalTime

在 Spring Boot 中进行请求验证时,响应不符合预期