如何在Java的LocalDateTime和LocalDate上配置Jackson序列化?

时间:2018-07-25 21:17:28

标签: java serialization jackson

我知道Stackoverflow上有很多与此主题相关的文章,我敢肯定我已经阅读了所有这些文章,但是我仍在努力使这项工作正常进行,并且希望获得任何指导。

这是我正在使用的Spring Parent和Jackson依赖关系:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.9.RELEASE</version>
</parent>

<!-- Jackson -->
<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>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
</dependency>

在我的应用程序配置中,我尝试使用:

@Autowired
void configureJackson(ObjectMapper jackson2ObjectMapper) {

    JavaTimeModule timeModule = new JavaTimeModule();

    timeModule.addDeserializer(LocalDate.class,
            new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));

    timeModule.addDeserializer(LocalDateTime.class,
            new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));

    timeModule.addSerializer(LocalDate.class,
            new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));

    timeModule.addSerializer(LocalDateTime.class,
            new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));

    jackson2ObjectMapper
            .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
            .setSerializationInclusion(JsonInclude.Include.NON_NULL)
            .registerModule(timeModule)
            .registerModule(new ParameterNamesModule())
            .registerModule(new Jdk8Module())
            .registerModule(new JtsModule());
}

这是我正在测试的模型。 (我正在尝试在5-6个模型中实现相同的效果。

public class DateRange implements Serializable {

     private static final long serialVersionUID = 6412487507434252330L;

     private LocalDateTime startTime;
     private LocalDateTime endTime;

     private LocalDate startDate;
     private LocalDate endDate;

     // Getters/Setters

我希望我可以找到一种适用于全球的方法,而无需我单独注释每个字段。我以前使用过java.util.Date,但是在那里遇到了其他功能的问题。

尝试使用这些更新的(更好的)日期模型而不是那些损坏的旧模型使我对一件简单的事情感到非常头痛。


更新

我将配置更改为以下建议的一种,确实可以解决此问题。

@Bean
@Primary
public ObjectMapper objectMapper() {

    JavaTimeModule timeModule = new JavaTimeModule();

    timeModule.addDeserializer(LocalDate.class,
            new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));

    timeModule.addDeserializer(LocalDateTime.class,
            new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));

    timeModule.addSerializer(LocalDate.class,
            new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));

    timeModule.addSerializer(LocalDateTime.class,
            new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));

    return new ObjectMapper()
            //.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
            .setSerializationInclusion(JsonInclude.Include.NON_NULL)
            .registerModule(timeModule)
            .registerModule(new ParameterNamesModule())
            .registerModule(new Jdk8Module())
            .registerModule(new JtsModule());
}

现在我唯一的问题是LocalDateTime在需要时打印类似“ 2018-07-26T07:57:12.938”的时间戳:2018-07-26 07:57:12。

这些字段现在已经在使用中,我需要以一种不需要我的API使用者进行任何调整的方式无缝进行此更改。

Cassio提到禁用SerializationFeature.WRITE_DATES_AS_TIMESTAMPS将以这种ISO格式打印时间戳,但这不是我所需要的。我试图注释掉该字段,希望它能提取我提供的自定义DateTimeFormatter,但是它并没有改变我的输出。

3 个答案:

答案 0 :(得分:3)

JavaTimeModule将为您完成艰苦的工作。它为serializers类型提供了一组deserializersjava.time。如果SerializationFeature.WRITE_DATES_AS_TIMESTAMPS被禁用 ,则java.time类型将以标准的ISO-8601字符串表示形式进行序列化。


默认情况下,Spring将为您提供由ObjectMappper创建的Jackson2ObjectMapperBuilder的实例。该实例是为您自动配置的。有关详细信息,请参见类documentation

如果要完全替换默认的ObjectMapper,请定义该类型的@Bean并将其标记为@Primary

@Bean
@Primary
public ObjectMapper objectMapper() {    
    ObjectMapper mapper = new ObjectMapper();
    mapper.registerModule(new JavaTimeModule());
    mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
    return mapper;
}

或者,如果您更喜欢基于生成器的方法,请定义一个Jackson2ObjectMapperBuilder @Bean

@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
    Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
    builder.modules(new JavaTimeModule());
    builder.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
    return builder;
}

请注意,无论哪种情况,都将禁用ObjectMapper的所有自动配置。有关详细信息,请参见documentation

答案 1 :(得分:0)

您还可以解决此问题以公开此实例:

ERROR:  syntax error at or near "Docking"
LINE 4: (2,'Docking Station','AS-0201764-RT','275-4197991-QC-53','Eq...
            ^
********** Error **********
ERROR: syntax error at or near "Docking"
SQL state: 42601
Character: 348


INSERT INTO assets (id, name, asset_tag, asset_serial_number, asset_type, product_descrption, asset_status, warranty_date, warranty_length, employee_id) 
VALUES 
(1,'Monitor','AS-8153000-DP','358-7190353-JD-44', 'Equipment', 'A display screen used to provide visual output from a computer', 'Assigned', '2018-01-08', '1 year', 'ZO-9440’ ),
(2,'Docking Station','AS-0201764-RT','275-4197991-QC-53','Equipment', 'A device in which a laptop computer, smartphone, or other mobile device may be placed for charging','Assigned','2017-07-12','1 year','ZO-9440’), 

答案 2 :(得分:0)

我终于在Cassio的帮助下以及在网络上进行了其他一些挖掘工作。回顾过去,我认为问题是我在JavaTimeModule上定义了自定义格式,但是我需要在映射器上定义它们。

@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
    return new Jackson2ObjectMapperBuilder()
            .createXmlMapper(false)
            .indentOutput(true)
            .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
            .serializers(
                    new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")),
                    new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
            .deserializers(
                    new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")),
                    new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
            .modules(
                    new JavaTimeModule(),
                    new ParameterNamesModule(),
                    new Jdk8Module(),
                    new JtsModule());
}

https://github.com/spring-projects/spring-boot/issues/4217

http://www.baeldung.com/jackson-serialize-dates