【问题标题】:Serialize java.time.localdate into json using Jackson使用 Jackson 将 java.time.localdate 序列化为 json
【发布时间】:2015-04-29 00:19:09
【问题描述】:

我正在编写一个 Java 8 Spring MVC 应用程序,该应用程序使用 REST 服务与旧的 Progress OpenEdge 应用程序通信(为此我使用 Spring 的 RestTemplate)。我需要读取和写入 Progress 应用程序的数据包含一些日期。在 Java 应用程序中,我使用 java.time.LocalDate 数据类型来表示这些字段,并且我正在使用 Jackson 将数据序列化/反序列化到 Json 中。

我遇到的问题如下。当我从 Progress Application 发送数据时,日期以“2015-01-02”的形式发送,并按预期作为 LocalDate 存储在我的 Java 实体中。当数据发送到 Web 前端时,Json 还包含相同格式的日期。当我在 Web 前端更改信息并应用它时,它也会作为“2015-01-02”发送回 Java 应用程序,并再次作为 LocalDate 存储而没有问题。但是当我将数据继续发送到 Progress 应用程序时,我收到的 Json 不包含日期为“2015-01-02”,而是包含三个字段(2015.0、1.0、2.0)的数组,并且 Progress 应用程序是无法将其分配回数据库中的日期字段。

当然,我可以在 Progress 端编写一个转换以将数组转换回日期,但我想避免这种情况,因为我希望日期始终以 ISO 8601 格式发送。

根据我在 Jackson 上找到的信息,当启用 WRITE_DATES_AS_TIMESTAMPS 时,java.time.LocalDate 表示为一个数组,但我禁用了这个(当日期发送到 Web 前端时,它不是作为数组发送...)

以下是一些相关代码:

CustomObjectMapper:

@Service
public class CustomObjectMapper extends ObjectMapper
{
  public CustomObjectMapper()
  {
    this.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,
                   false);
  }
}

我的 servlet.xml 中的配置

<mvc:annotation-driven>
  <mvc:message-converters>
    <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
      <property name="objectMapper" ref="customObjectMapper"/>
    </bean>
  </mvc:message-converters>
</mvc:annotation-driven>

<bean id="customObjectMapper" class="com.msoft.utility.CustomObjectMapper"/>

字段定义:

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

我将 Java 8 与 Spring 4.1.5 和 Jackson 2.5.1 一起使用。

任何提示我如何使它工作或寻找解决方案将不胜感激,因为我已经为此工作了近 2 天...

谢谢

编辑:

一些额外的信息...

我在 pom.xml 中包含了 Jackson JSR-310 模块。这是我的 pom 文件的相关部分...

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-core</artifactId>
  <version>2.5.1</version>
</dependency>
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-annotations</artifactId>
  <version>2.5.1</version>
</dependency>
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.5.1</version>
</dependency>
<dependency>
  <groupId>com.fasterxml.jackson.datatype</groupId>
  <artifactId>jackson-datatype-jsr310</artifactId>
  <version>2.5.1</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-test</artifactId>
  <version>4.1.5.RELEASE</version>
  <scope>test</scope>
  <type>jar</type>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-webmvc</artifactId>
  <version>4.1.5.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.springframework.data</groupId>
  <artifactId>spring-data-jpa</artifactId>
  <version>1.7.2.RELEASE</version>
</dependency>

另外,如果我理解正确,Spring 会在检测到该模块时自动注册它。查看Jackson2ObjectMapperFactoryBean上的信息

请注意,Jackson 的 JSR-310 和 Joda-Time 支持模块将 可用时自动注册(以及当 Java 8 和 Joda-Time 它们分别可用)。

所以我认为我不应该做任何其他事情来让它正常工作,但显然我仍然缺少一些东西......

【问题讨论】:

  • 对于它的价值,如果模块已正确注册,则不应使用注释。将使用注释覆盖,并且不调用已注册的默认处理程序。这可能很重要,也可能无关紧要,因为初始化略有不同。
  • 如果我删除了deliveryDate属性的注释,日期是从Java作为具有以下结构的对象发送的:{"year":2015,"month":"JANUARY","dayOfMonth" :2,"dayOfWeek":"FRIDAY","era":"CE","dayOfYear":2,"leapYear":false,"monthValue":1,"chronology":{"id":"ISO", "calendarType":"iso8601"}} 而不是我想要的 2015/01/02。感谢您的帮助,但仍然不是我要找的...
  • 同样的问题...你找到解决办法了吗
  • 嗨,我刚刚检查了我们的代码,看来最后我只是在进度方面写了一个转换来转换日期中的数组(这并不难...)。该项目已交付给客户,似乎运行良好。由于我已经有 4 到 5 个月没有从事这个项目了,所以我无法尝试 Niclas 提出的解决方案。也许你应该调查一下。如果有帮助,请告诉我,我会接受他的回答作为解决方案。

标签: java json spring jackson


【解决方案1】:

我想你只需要注册 JSR-310 (Java 8 Date/Time) 模块:

https://github.com/FasterXML/jackson-datatype-jsr310/

因为 Jackson 核心不能依赖任何 Java 8 功能(此时的基线,2.5,是 Java 6)。无论如何,对大多数数据类型库的支持都将通过插件模块。

【讨论】:

  • 废话,我忘了提...但是我的 pom.xml 中包含了那个模块。我会用一些额外的信息更新我的问题...
【解决方案2】:

这对我有用,我没有使用 Spring boot。

@Configuration
@EnableWebMvc
public class SpringMvcConfiguration extends WebMvcConfigurerAdapter {

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
        builder.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        converters.add(new MappingJackson2HttpMessageConverter(builder.build()));
    }
}

【讨论】:

  • 添加了 configureMessageConverters 部分,因为没有它它将无法工作:p
  • 一定要禁用SerializationFeature.WRITE_DATES_AS_TIMESTAMPS 而不是SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS。它们看起来一样,但只是第一次工作。调试了 2 个小时。
猜你喜欢
  • 2016-01-02
  • 1970-01-01
  • 2012-04-07
  • 1970-01-01
  • 2016-06-14
  • 2013-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多