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

And*_*ser 10 java spring json spring-boot jackson2

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

我在以下位置配置了以下与Jackson相关的设置application.properties:

spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=false
Run Code Online (Sandbox Code Playgroud)

序列化主要按照我的需要工作.尽管如此,我注意到杰克逊似乎已经截止了毫秒数000.

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

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

测试2:使用设置为某些非000值的毫秒序列化Instant :

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

问题:

  • 是设计的那种行为?
  • 有什么我可以做的强制序列化000

Sea*_*oll 5

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

解决方法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);
Run Code Online (Sandbox Code Playgroud)

解决方法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);
Run Code Online (Sandbox Code Playgroud)

*链接已失效,因为他们弃用了 FasterXML/jackson-datatype-jsr310 并将其移至jackson-modules-java8。请参阅https://github.com/FasterXML/jackson-modules-java8/issues/76


Gus*_*avo 5

我使用这种方法解决:

ObjectMapper objectMapper = new ObjectMapper();
JavaTimeModule module = new JavaTimeModule();
module.addSerializer(Instant.class, new InstantSerializerWithMilliSecondPrecision());
objectMapper.registerModule(module);
Run Code Online (Sandbox Code Playgroud)

对于 InstantSerializerWithMilliSecondPrecision 我使用了这个:

public class InstantSerializerWithMilliSecondPrecision extends InstantSerializer {

    public InstantSerializerWithMilliSecondPrecision() {
        super(InstantSerializer.INSTANCE, false, new DateTimeFormatterBuilder().appendInstant(3).toFormatter());
    }
}
Run Code Online (Sandbox Code Playgroud)

现在 Instant 序列化总是包括毫秒。示例:2019-09-27T02:59:59.000Z