Force Milliseconds When Serializing Instant to ISO8601 using Jackson
There appears to be a Jackson issue open for this here*. That link contains two workarounds
Workaround 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);
Workaround 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 is dead because they deprecated FasterXML/jackson-datatype-jsr310 and moved it to jackson-modules-java8. See https://github.com/FasterXML/jackson-modules-java8/issues/76
I solve using this aproach:
ObjectMapper objectMapper = new ObjectMapper();JavaTimeModule module = new JavaTimeModule();module.addSerializer(Instant.class, new InstantSerializerWithMilliSecondPrecision());objectMapper.registerModule(module);
And for InstantSerializerWithMilliSecondPrecision i used this:
public class InstantSerializerWithMilliSecondPrecision extends InstantSerializer { public InstantSerializerWithMilliSecondPrecision() { super(InstantSerializer.INSTANCE, false, new DateTimeFormatterBuilder().appendInstant(3).toFormatter()); }}
Now the Instant serialization always includes milliseconds. Example: 2019-09-27T02:59:59.000Z
None of two workarounds mentioned by Sean Carroll works me. I end up with writing my own serializer for Instant.
final ObjectMapper mapper = new ObjectMapper();final JavaTimeModule javaTimeModule = new JavaTimeModule();javaTimeModule.addSerializer(Instant.class, new KeepMillisecondInstantSerializer());mapper.registerModule(javaTimeModule);public class KeepMillisecondInstantSerializer extends JsonSerializer<Instant> { private final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX") .withZone(ZoneId.of("UTC")); @Override public void serialize(final Instant instant, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider) throws IOException { final String serializedInstant = dateTimeFormatter.format(instant); jsonGenerator.writeString(serializedInstant); }}
I guess Jackson use Instant.toString()
method to serialize Instant objects by default. I also find some discussions about Instant.toString()
method on StackOverflow.