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

问题描述 投票:0回答:7

在 Spring Boot 1.2.3.RELEASE 中使用 fastxml 将

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());
    }
    

以上都没有帮助。

json date serialization spring-boot spring-data-rest
7个回答
30
投票
compile ("com.fasterxml.jackson.datatype:jackson-datatype-jsr310")

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

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

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


15
投票

在我的 Spring Boot 2 应用程序中

  • @JsonFormat
    注释用于 REST 控制器中(反)序列化 JSON 数据时。
  • @DateTimeFormat
    注释用于其他控制器
    ModelAttribute
    当(反)序列化字符串数据时。

您可以在同一字段上指定两者(如果您在 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”


5
投票

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

@JsonFormat
注释。

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

5
投票

实际上,只要在 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 上测试。


3
投票

您可能有兴趣在全局注册它,而不是为所有 LocalDate 属性指定序列化器/反序列化器。您需要重写 Spring 用于序列化/反序列化的默认 ObjectMapper 的配置。这是一个例子:

@Configuration
public class ObjectMapperConfiguration {

    @Bean
    @Primary
    public ObjectMapper objectMapper() {
        ObjectMapper mapper = new ObjectMapper();

        // Registro global do serializer/deserializer para datas sem horário
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(LocalDate.class, new LocalDateSerializer());
        simpleModule.addDeserializer(LocalDate.class, new LocalDateDeserializer());

        mapper.registerModule(simpleModule);
        return mapper;
    }
}

这样,Jackson 将始终对定义的数据类型使用指定的序列化器/反序列化器,而无需注释类属性。

信息:您必须将 jackson-databind 依赖项添加到 pom.xml 才能拥有自定义序列化器/反序列化器代码功能:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.3</version>
</dependency>

0
投票
 @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));
    };
}

0
投票

您可能会在不同的课程中使用

LocalDateTime
LocalDate
。创建一个配置类并添加自定义
ObjectMapper
bean 可以提供帮助:

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class CustomMapper {
    @Bean
    public ObjectMapper objectMapper(){
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.registerModule(new JavaTimeModule());
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
//The below helped me to solve the issue
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        return objectMapper;
    }
© www.soinside.com 2019 - 2024. All rights reserved.