javajacksonjava-timejsr310

Serialize LocalDateTime with only milliseconds with Jackson


I want to serialize a LocalDateTime to textual format while only showing milliseconds. I tried the following example:

final ObjectMapper mapper = new ObjectMapper();

mapper.registerModule(new Jdk8Module());
mapper.registerModule(new JavaTimeModule());
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
mapper.disable(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS);

final LocalDateTime t = LocalDateTime.of(2014, 3, 30, 12, 30, 23, 123456789);

System.out.println(mapper.writeValueAsString(t));

This outputs:

"2014-03-30T12:30:23.123456789"

So the precision is still in nanoseconds, despite to not show them as per mapper.disable(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS).

I expected:

"2014-03-30T12:30:23.123"

Why is this? How can I fix this?


Solution

  • Since you disabled WRITE_DATES_AS_TIMESTAMPS, enabling or disabling WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS does nothing because localDateTime isn't in the timestamp representation anymore.

    If you enable WRITE_DATES_AS_TIMESTAMPS and then disable WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS, you'll get the desired result but in another form ([2014,3,30,12,30,23,123]), so it's also not an option.

    So there are basically only two options to achieve the expected result:

    1. The easiest - use this: System.out.println(mapper.writeValueAsString(t.truncatedTo(ChronoUnit.MILLIS)));

      (Remember that you can safely remove mapper.disable(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS);, as it does nothing in this case).

    2. A more complicated way (without truncating the time):

      DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS");
      SimpleModule simpleModule = new SimpleModule();
      simpleModule.addSerializer(new LocalDateTimeSerializer(dateTimeFormatter));
      
      final ObjectMapper mapper = new ObjectMapper();
      mapper.registerModule(simpleModule);
      
      final LocalDateTime t = LocalDateTime.of(2014, 3, 30, 12, 30, 23, 123456789);
      
      System.out.println(mapper.writeValueAsString(t));
      

      (In that case you don't even need to use JavaTimeModule).