使用 Jackson 将即时序列化为 ISO8601 时强制毫秒

2022-09-03 02:20:14

我有一些与 JSON 序列化相关的问题,在我使用的项目中使用 Jackson 和 .Spring Boot 2.0.0.M6Spring Framework 5.0.1.RELEASEJackson 2.9.2

我已经在中配置了以下与杰克逊相关的设置:application.properties

spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=false

序列化主要按照我的需要工作。尽管如此,我注意到杰克逊似乎切断了毫秒,如果他们是.000

测试 1:序列化即时,毫秒设置为 000

  • 使用初始化即时字段Instant.parse("2017-09-14T04:28:48.000Z")
  • 使用 Jackson 序列化它
  • 输出将为"2017-09-14T04:28:48Z"

测试 2:序列化即时,并将毫秒数设置为某个非 000 值:

  • 使用初始化即时字段Instant.parse("2017-09-14T04:28:48.100Z")
  • 使用 Jackson 序列化它
  • 输出将为"2017-09-14T04:28:48.100Z"

问题

  • 这种行为是设计使然吗?
  • 我能做些什么来强制序列化 ?000

答案 1

我用这个aproach解决:

ObjectMapper objectMapper = new ObjectMapper();
JavaTimeModule module = new JavaTimeModule();
module.addSerializer(Instant.class, new InstantSerializerWithMilliSecondPrecision());
objectMapper.registerModule(module);

对于InstantSerializerWithMilliSecondPrecision,我使用了这个:

public class InstantSerializerWithMilliSecondPrecision extends InstantSerializer {

    public InstantSerializerWithMilliSecondPrecision() {
        super(InstantSerializer.INSTANCE, false, new DateTimeFormatterBuilder().appendInstant(3).toFormatter());
    }
}

现在,即时序列化始终包含毫秒。示例:2019-09-27T02:59:59.000Z


答案 2

这里似乎有一个杰克逊的问题*。该链接包含两种解决方法

解决方法 1

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

解决方法 2

JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(ZonedDateTime.class,
  new ZonedDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX")));
ObjectMapper mapper = new ObjectMapper().registerModule(javaTimeModule);

*Link已经死了,因为他们弃用了FasterXML/jackson-datatype-jsr310,并将其移动到jackson-modules-java8。查看 https://github.com/FasterXML/jackson-modules-java8/issues/76