jackson - Java 8 DateTime 序列化和 Jackson JSR 310

标签 jackson spring-boot jsr310

我在 Spring Boot 应用程序中使用 Java 8 DateTime 和 Jackson jsr 310 支持。

我禁用了SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,以强制 Jackson 将 localDatetime 序列化为字符串而不是 int 数组。

但是当日期时间微秒或九秒以 0 结尾时,我发现了一个奇怪的格式问题。我认为序列化结果可能等于 date.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME),但事实并非如此,format方法省略了零。

完整的示例测试代码。

private LocalDateTime date;

private OffsetDateTime offsetDate;

private ZonedDateTime zonedDate;

@Before
public void setup() throws ServletException {
    date = LocalDateTime.of(2015, 8, 15, 11, 40, 10, 100_000_000);
    offsetDate = OffsetDateTime.of(2015, 8, 15, 11, 40, 10, 100_000_000, ZoneOffset.ofHours(8));
    zonedDate = ZonedDateTime.of(2015, 8, 15, 11, 40, 10, 100_000_000, ZoneId.of("Asia/Shanghai"));
}

@Test
public void testDateFormat() throws Exception {
    Map<String, Object> map = new HashMap<>();
    map.put("localDate", date);
    map.put("offsetDate", offsetDate);
    map.put("zonedDate", zonedDate);

    String json = objectMapper.writeValueAsString(map);

    log.debug("converted json result @" + json);

    JsonNode rootNode = objectMapper.readTree(json);

    JsonNode localDateNode = rootNode.get("localDate");
    assertEquals("local date should be equals", date.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME), localDateNode.textValue());

    JsonNode offsetDateNode = rootNode.get("offsetDate");
    assertEquals("offsetDate date should be equals", offsetDate.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME), offsetDateNode.textValue());

    JsonNode zonedDateNode = rootNode.get("zonedDate");
    assertEquals("zonedDate date should be equals", zonedDate.format(DateTimeFormatter.ISO_ZONED_DATE_TIME), zonedDateNode.textValue());

}

测试失败,打印调试日志

{
    "zonedDate":"2015-08-15T11:40:10.100+08:00[Asia/Shanghai]",
    "localDate":"2015-08-15T11:40:10.100",
    "offsetDate":"2015-08-15T11:40:10.1+08:00"
}

zonedDatelocalDate 微秒以 00 结尾,但 offsetDate 不是。并且date.format也得到不同的结果,其中微秒00结尾。

format、toString、json文本的打印结果

LocalDateTime format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)@2015-08-15T11:40:10.1
LocalDateTime toString                                     @2015-08-15T11:40:10.100
LocalDateTime serialized json node text                    @2015-08-15T11:40:10.100
OffsetDateTime format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)@2015-08-15T11:40:10.1+08:00
OffsetDateTime toString                                      @2015-08-15T11:40:10.100+08:00
OffsetDateTime serialized json node text                     @2015-08-15T11:40:10.1+08:00
ZonedDateTime format(DateTimeFormatter.ISO_ZONED_DATE_TIME)@2015-08-15T11:40:10.1+08:00[Asia/Shanghai]
ZonedDateTime toString                                     @2015-08-15T11:40:10.100+08:00[Asia/Shanghai]
ZonedDateTime serialized json node text                    @2015-08-15T11:40:10.100+08:00[Asia/Shanghai]
  1. 看来toString结果应该是 jackson 序列化中所需的结果,在上面的日志记录中,OffsetDateTime json节点微秒文本应该以00结尾 .
  2. 为什么格式方法结果省略结尾00

完整的示例代码可以在我的github.com找到。

angular-springmvc-sample-boot

ISODateTest

最佳答案

作为解决方法,我添加了自己的序列化器:

    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.registerModule(new JavaTimeModule());
    SimpleModule module = new SimpleModule();
    module.addSerializer(ZonedDateTime.class, new JsonSerializer<ZonedDateTime>() {
        @Override
        public void serialize(ZonedDateTime zonedDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
            jsonGenerator.writeString(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZZZ").format(zonedDateTime));
        }
    });
    objectMapper.registerModule(module);
    objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
    objectMapper.enable(SerializationFeature.INDENT_OUTPUT);

关于jackson - Java 8 DateTime 序列化和 Jackson JSR 310,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32026837/

相关文章:

java - 如何使用 Jackson 反序列化 Map<?, ?> ?

java - 解析可用对象的奇怪 xml 响应

spring-boot - 定义为 null 的 bean 'metaDataSourceAdvisor' 无法注册

java - Jackson库的ANDROID使用: How to load object with indexes - range from to

java - 如何在使用 Spring 创建期间配置 kafka 主题保留策略?

java - Spring 集成测试环境不调度 JPA 实体生命周期事件

javascript - 如何在js-joda中进行严格的LocalDate解析?

java - 如何使用 Spring MVC 将表单参数绑定(bind)到 Java 8 Duration?

java - 使用 LocalDateTime 的“AttributeConverter 和显式类型不能应用于同一属性”

java - 解码 JsonNode 更改数据类型