ocalDateTime和LocalDate上配置Jackson

ocalDateTime和LocalDate上配置Jackson

本文介绍了如何在Java的LocalDateTime和LocalDate上配置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,但是它并没有改变我的输出.

解决方案

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


默认情况下,Spring将为您提供 ObjectMappper Jackson2ObjectMapperBuilder .该实例是为您自动配置的.参见类文档以获取详细信息.

如果要替换默认的 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 .请参阅文档了解详情.

I know that there are many posts on Stackoverflow regarding this topic and I'm sure I've read just about all of them, but I am still struggling to get this working and would appreciate any guidance.

This is the Spring Parent and Jackson Dependencies I am using:

<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>

Within my Application Configuration I am trying to use:

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

This is the model I am testing with. (I am trying to achive the same in 5-6 models).

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

I am hoping that I could find an approach that would apply globally without the need for me to annotate each field individually. I was using java.util.Date before, but ran into some issues with other functionality there.

Trying to use these newer (better) date models instead of that old damaged one is causing me a lot of headache over a simple thing.


Update

I changed my configuration to one of the suggested below and came really close to solving this issue.

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

Now the only issue I have is that LocalDateTime is printing timestamps like: "2018-07-26T07:57:12.938" when I need them like: 2018-07-26 07:57:12.

These fields are already in-use today and I need to make this change seamless in a way that doesn't require my API consumers to make any adjustments.

Cassio mentioned that disabling SerializationFeature.WRITE_DATES_AS_TIMESTAMPS will print timestamps in this ISO format, but it's not what I need. I tried to comment out the field in the hopes that it would pickup the custom DateTimeFormatter I am providing, however it has not changed my output.

解决方案

The JavaTimeModule will do the hard work for you. It provides a set of serializers and deserializers for for the java.time types. If the SerializationFeature.WRITE_DATES_AS_TIMESTAMPS is disabled, java.time types will be serialized in standard ISO-8601 string representations.


By default, Spring will provide you with an instance of ObjectMappper created by the Jackson2ObjectMapperBuilder. This instance is auto-configured for you. See the class documentation for details.

If you want to replace the default ObjectMapper completely, either define a @Bean of that type and mark it as @Primary:

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

Or, if you prefer the builder-based approach, define a Jackson2ObjectMapperBuilder @Bean.

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

Note that, in either case, doing so disables all auto-configuration of the ObjectMapper. See the documentation for details.

这篇关于如何在Java的LocalDateTime和LocalDate上配置Jackson序列化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-30 19:02