有效的方法,让Jackson串行化Java 8即时作为纪元毫秒?

ehxuflar  于 2022-10-30  发布在  Spring
关注(0)|答案(4)|浏览(349)

使用Spring RestControllers和JacksonJSON解析后端,在前端使用AngularJS。我正在寻找一种有效的方法,让Jackson将Instant序列化为epoch毫秒,以便后续方便地使用JavaScript代码。(在浏览器端,我希望通过Angular的Date Filter{{myInstantVal | date:'short' }}(用于我所需的日期格式)。
在Java方面,Jackson使用的getter很简单:

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()上,这样我就不必创建这些额外的方法了吗?

0wi1tuuw

0wi1tuuw1#

你只需要阅读你链接到的README。强调我的:

如果启用了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,则时间戳将以毫秒为整数写入。

1mrurvl1

1mrurvl12#

添加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>
(上面的register-defaults默认为true,并且很可能是您希望Spring按原样配置其他转换器的值)。
1.如下所示覆盖MapJackson 2 HttpMessageConverter:

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

第1步很重要,因为SpringMVC将忽略已配置的MJ 2 HMC对象,而使用它自己的默认对象。
部分H/T this SO柱。

kgqe7b3p

kgqe7b3p3#

在Instant属性的JSON响应中返回epoch米利斯的简单方法如下:

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

这将导致以下响应:

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

szqfcxe24#

这就是我在Kotlin中使用的方法(Java也应该是这样)。

data class MyPojo(
  @JsonFormat(without = [JsonFormat.Feature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS])
  val timestamp: Instant
)

相关问题