如何在 Java 的 LocalDateTime 和 LocalDate 上配置 Jackson 序列化? [英] How do I configure Jackson Serialization on LocalDateTime and LocalDate for Java?

查看:37
本文介绍了如何在 Java 的 LocalDateTime 和 LocalDate 上配置 Jackson 序列化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道在 Stackoverflow 上有很多关于这个主题的帖子,我相信我已经阅读了几乎所有的帖子,但我仍然在努力让它工作,并希望得到任何指导.

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.

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

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

这是我正在测试的模型.(我正在尝试在 5-6 个模型中实现相同的目标).

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

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

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.

更新

我将我的配置更改为下面建议的配置之一,并且非常接近于解决这个问题.

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

现在我唯一的问题是 LocalDateTime 正在打印时间戳,例如:2018-07-26T07:57:12.938",当我需要它们时,例如:2018-07-26 07:57:12.

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.

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

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 提到禁用 SerializationFeature.WRITE_DATES_AS_TIMESTAMPS 会以这种 ISO 格式打印时间戳,但它是不是我需要的.我试图注释掉该字段,希望它能选择我提供的自定义 DateTimeFormatter,但它并没有改变我的输出.

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.

推荐答案

JavaTimeModule 将为您完成繁重的工作.它提供了一组 序列化程序反序列化器 用于 java.time 类型.如果 SerializationFeature.WRITE_DATES_AS_TIMESTAMPS禁用java.time 类型将在标准ISO-8601 字符串表示.

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.

默认情况下,Spring 会为你提供一个 ObjectMappperJackson2ObjectMapperBuilder.此实例是为您自动配置的.请参阅类 文档了解详情.

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.

如果要替换默认的ObjectMapper 完全,要么定义一个 @Bean 并将其标记为 @Primary:

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

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

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

请注意,在任何一种情况下,这样做都会禁用 ObjectMapper.请参阅文档 了解详情.

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

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

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆