将 LocalDate 和 LocalDateTime 序列化为 Unix 时间戳

wat*_*ery 5 java spring spring-mvc jackson java-time

我正在从在 Spring MVC 应用程序中使用新类java.sql.Timestamp转向java.util.GregorianCalendar使用新类。java.time.*

所以我改变了每一个

private GregorianCalendar field;
Run Code Online (Sandbox Code Playgroud)

private LocalDate field;
Run Code Online (Sandbox Code Playgroud)

或者

private LocalDateTime field;
Run Code Online (Sandbox Code Playgroud)

但现在当序列化这些 bean 时,它们会像这样序列化:

"field": {
      "year": 1970,
      "month": "JANUARY",
      "dayOfMonth": 18,
      "dayOfWeek": "SUNDAY",
      "era": "CE",
      "dayOfYear": 18,
      "leapYear": false,
      "monthValue": 1,
      "chronology": {
        "id": "ISO",
        "calendarType": "iso8601"
      }
    },
Run Code Online (Sandbox Code Playgroud)

我找到了其他问题的答案,提到添加对jackson-datatype-jsr310 的依赖项并获得:

 "field": [
      1970,
      1,
      18
    ],
Run Code Online (Sandbox Code Playgroud)

但我在序列化时仍然想要一个 unix 时间戳,就像我在字段中得到的那样GregorianCalendar:我怎样才能实现这一点?我可以避免使用自定义序列化器(和反序列化器)吗?

这些与资源响应和请求主体(如 POST、PUT 等)相关,而不是请求参数。

Jackson 的ObjectMapper配置如下:

jacksonConverter.getObjectMapper().enable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
jacksonConverter.getObjectMapper().disable(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS);
Run Code Online (Sandbox Code Playgroud)

Tom*_*ski 3

在JavaDoc to JavaTimeModule(包含在jackson-datatype-jsr310库中)中,我们可以阅读以下内容:

如果启用该功能,大多数java.time类型都会序列化为数字(适当的整数或小数) [...]SerializationFeature.WRITE_DATES_AS_TIMESTAMPS

[...] 如果SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS禁用,时间戳将写入毫秒整数。[...]

进而:

此标准序列化/反序列化规则的一些例外:

  • [...]
  • LocalDateLocalTimeLocalDateTimeOffsetTime,它们无法可移植地转换为时间戳,而是在WRITE_DATES_AS_TIMESTAMPS启用时表示为数组。

您确实可以看到它LocalDateTime不能普遍转换为 Unix 时间戳,因为它的toEpochSecond方法作为ZoneOffset参数。

总而言之,您能做的最好的事情似乎就是替换LocalDateTimeInstant(有关和 之间差异的解释,请参阅这个很好的答案)。LocalDateTimeInstant

除此之外,您确实需要自定义JsonSerializerJsonDeserializer.


这是一个工作代码示例:

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;
}
Run Code Online (Sandbox Code Playgroud)