有效的方法让杰克逊将Java 8 Instant序列化为纪元毫秒?

时间:2016-06-23 19:01:26

标签: angularjs json spring jackson java-time

使用带有Jackson JSON解析后端的Spring RestControllers,前端使用AngularJS。我正在寻找一种有效的方法让Jackson序列化一个Instant作为纪元毫秒,以便随后使用JavaScript代码。 (在浏览器方面,我希望通过Angular Date Filter{{myInstantVal | date:'short' }}为我所需的日期格式提供时代ms。)

在Java方面,杰克逊将使用的吸气剂只是:

public Instant getMyInstantVal() { return myInstantVal; }

序列化不会按原样运行,因为jackson-datatype-jsr310默认情况下不会为Instant返回Epoch毫秒。我看着将@JsonFormat添加到上面的getter中以将Instant变形为前端可以使用的东西,但它遇到两个问题:(1)我可以提供它的模式显然仅限于SimpleDateFormat,它没有'提供“epoch毫秒”选项,以及(2)当我尝试将Instant作为格式化日期发送到浏览器时,Jackson会抛出异常,因为@JsonFormat注释需要Instants的TimeZone属性,我不这样做希望硬编码,因为它会因用户而异。

到目前为止,我的解决方案(并且工作正常)是使用@JsonGetter创建替换的getter,这会导致Jackson使用此方法来序列化myInstantVal

@JsonGetter("myInstantVal")
public long getMyInstantValEpoch() {
    return myInstantVal.toEpochMilli();
}

这是正确的方法吗?或者是否有一个很好的注释我错过了我可以使用getMyInstantVal()所以我不必创建这些额外的方法?

3 个答案:

答案 0 :(得分:11)

您只需阅读链接到的自述文件。强调我的:

  

如果启用了SerializationFeature#WRITE_DATES_AS_TIMESTAMPS功能,则大多数JSR-310类型被序列化为数字(适当时为整数或小数),否则将以标准ISO-8601字符串表示形式序列化。

     

[...]

     

时间戳的粒度通过配套功能SerializationFeature#WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS和DeserializationFeature#READ_DATE_TIMESTAMPS_AS_NANOSECONDS来控制。对于序列化,时间戳写为小数(小数),其中数字为秒,小数为小数秒,如果启用WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS(默认情况下),分辨率可以为纳秒,具体取决于基础JDK实现。 如果禁用WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS,则时间戳将写为整数毫秒。

答案 1 :(得分:1)

添加JB的答案,覆盖Spring MVC的默认JSON解析器,从Instant(以及其他拥有它们的Java 8日期对象)中剥离纳秒:

  1. 在mvc:annotation-driven元素中,指定您将覆盖默认的JSON消息转换器:

    <mvc:annotation-driven validator="beanValidator"> <mvc:message-converters register-defaults="true"> <beans:ref bean="jsonConverter"/> </mvc:message-converters> </mvc:annotation-driven>

  2. (默认情况下,寄存器默认值为true,很可能是您希望保持Spring按原样配置的其他转换器。

    1. 覆盖MappingJackson2HttpMessageConverter,如下所示:

      <beans:bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
      <beans:property name="objectMapper">
          <beans:bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
              <beans:property name="featuresToDisable">
                  <beans:array>
                      <util:constant static-field="com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS"/>
                  </beans:array>
              </beans:property>
          </beans:bean>
      </beans:property>
      

    2. 步骤#1非常重要,因为Spring MVC将忽略已配置的MJ2HMC对象而支持其自己的默认对象。

      部分H / T this SO帖子。

答案 2 :(得分:0)

在Instant属性的JSON响应中返回纪元毫秒的简单方法如下:

@JsonFormat(shape = JsonFormat.Shape.NUMBER, timezone = "UTC")
private Instant createdAt;

这将导致以下响应:

{
  ...
  "createdAt": 1534923249,
  ...
}