将LocalDate和LocalDateTime序列化为Unix时间戳 [英] Serialize LocalDate and LocalDateTime as Unix timestamps
问题描述
我正在使用 java.sql.Timestamp
和 java.util.GregorianCalendar
来使用 java.time。*
Spring MVC应用程序中的新类。
I'm moving from using java.sql.Timestamp
and java.util.GregorianCalendar
to employ java.time.*
new classes in a Spring MVC application.
所以我改变了每个
private GregorianCalendar field;
到
private LocalDate field;
或
private LocalDateTime field;
但现在序列化这些bean时,它们会像这样序列化:
But now when serializing those beans, they get serialized like this:
"field": {
"year": 1970,
"month": "JANUARY",
"dayOfMonth": 18,
"dayOfWeek": "SUNDAY",
"era": "CE",
"dayOfYear": 18,
"leapYear": false,
"monthValue": 1,
"chronology": {
"id": "ISO",
"calendarType": "iso8601"
}
},
我找到了其他问题的答案,提到依赖 jackson-datatype-jsr310 并获得:
I found answers to other questions that mention to add a dependency to jackson-datatype-jsr310 and obtained:
"field": [
1970,
1,
18
],
但序列化时我仍然想要一个unix时间戳,就像我用 GregorianCalendar
字段:我该如何实现?我可以避免使用自定义序列化程序(和反序列化程序)吗?
but I still want a unix timestamp when serializing like I got with GregorianCalendar
fields: how can I achieve that? Can I avoid a custom serializer (and deserializer)?
这些与资源响应和请求体(如POST,PUT等)相关,而不是与请求参数相关。
These are relevant for resource responses and request bodies (as in POST, PUT, etc), not for request parameters.
Jackson ObjectMapper
的配置如下:
The Jackson ObjectMapper
is configured like so:
jacksonConverter.getObjectMapper().enable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
jacksonConverter.getObjectMapper().disable(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS);
推荐答案
在JavaDoc中 JavaTimeModule (包括在 jackson-datatype-jsr310
library),我们可以阅读以下内容:
In the JavaDoc to JavaTimeModule (included in jackson-datatype-jsr310
library), we can read the following:
Most
java.time
如果启用了SerializationFeature.WRITE_DATES_AS_TIMESTAMPS
功能,则将类型序列化为数字(适当的整数或小数)[。 ..]
Most
java.time
types are serialized as numbers (integers or decimals as appropriate) if theSerializationFeature.WRITE_DATES_AS_TIMESTAMPS
feature is enabled [...]
[...]如果 SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS
被禁用,时间戳将被写为整数毫秒。 [...]
[...] If SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS
is disabled, timestamps are written as a whole number of milliseconds. [...]
然后:
此标准序列化/反序列化规则的一些例外情况:
Some exceptions to this standard serialization/deserialization rule:
- [...]
-
LocalDate
,LocalTime
,LocalDateTime
和OffsetTime
,当WRITE_DATES_AS_TIMESTAMPS
启用时,它无法转换为时间戳,而是表示为数组。
- [...]
LocalDate
,LocalTime
,LocalDateTime
, andOffsetTime
, which cannot portably be converted to timestamps and are instead represented as arrays whenWRITE_DATES_AS_TIMESTAMPS
is enabled.
您确实可以看到 LocalDateTime
无法无处不在地转换为Unix时间戳,因为它的 toEpochSecond 方法将 ZoneOffset
作为参数。
You can indeed see that LocalDateTime
cannot be ubiquitously converted to the Unix timestamp because its toEpochSecond method takes ZoneOffset
as parameter.
总结,你可以做的最好的事情就是用 Instant 替换
LocalDateTime
code>(参见这个很棒的答案解释 LocalDateTime
和 Instant
之间的区别。
To sum up, it seems the best thing you can do is replacing LocalDateTime
with Instant
(see this great answer for an explanation of the difference between LocalDateTime
and Instant
).
除此之外,你确实需要自定义 JsonSerializer
和 JsonDeserializer
。
Other than that, you would indeed need custom JsonSerializer
and JsonDeserializer
.
这是一个有效的代码示例:
Here's a working code sample:
public static void main(String[] args) throws Exception {
ObjectMapper objectMapper = new ObjectMapper()
.registerModule(new JavaTimeModule())
.disable(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS);
Entity entity = new Entity(Instant.now());
StringWriter writer = new StringWriter();
objectMapper.writeValue(writer, entity);
System.out.println(writer.getBuffer());
}
@lombok.Value
static class Entity {
Instant timestamp;
}
这篇关于将LocalDate和LocalDateTime序列化为Unix时间戳的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!