Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to serialize LocalDateTime with Jackson?

I got the following piece of code:

    ObjectMapper mapper = new ObjectMapper();
    mapper.registerModule(new JavaTimeModule());
    mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
    String now = new ObjectMapper().writeValueAsString(new SomeClass(LocalDateTime.now()));
    System.out.println(now);

And I get this:

{"time":{"hour":20,"minute":49,"second":42,"nano":99000000,"dayOfYear":19,"dayOfWeek":"THURSDAY","month":"JANUARY","dayOfMonth":19,"year":2017,"monthValue":1,"chronology":{"id":"ISO","calendarType":"iso8601"}}}

What I want to achieve is a string in ISO8601

2017-01-19T18:36:51Z

like image 513
user1745356 Avatar asked Jan 19 '17 18:01

user1745356


Video Answer


3 Answers

This is probably due to mistake in your code. You were using new unconfigured instance of mapper, here is the fix:

 ObjectMapper mapper = new ObjectMapper();
 mapper.registerModule(new JavaTimeModule());
 mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
 String now = mapper.writeValueAsString(new SomeClass(LocalDateTime.now()));
 System.out.println(now);
like image 50
Alexander Yanyshin Avatar answered Oct 14 '22 16:10

Alexander Yanyshin


This is what you can do for OffsetDateTime:

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "uuuu-MM-dd'T'HH:mm:ss.SSSXXXX")
private OffsetDateTime timeOfBirth;

For LocalDateTime you cannot use XXXX (zone offset) because there is no offset information. So you can drop it. But ISO8601 discourages using Local Time as it's ambiguous:

If no UTC relation information is given with a time representation, the time is assumed to be in local time. While it may be safe to assume local time when communicating in the same time zone, it is ambiguous when used in communicating across different time zones. Even within a single geographic time zone, some local times will be ambiguous if the region observes daylight saving time. It is usually preferable to indicate a time zone (zone designator) using the standard's notation.

like image 29
Stanislav Bashkyrtsev Avatar answered Oct 14 '22 16:10

Stanislav Bashkyrtsev


I use SimpleModule and the best practice for me is to have my own registered implementation for serialization and deserialization:

final SimpleModule localDateTimeSerialization = new SimpleModule();
    localDateTimeSerialization.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer());
    localDateTimeSerialization.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer());

objectMapper.registerModule(localDateTimeSerialization);

Serializer:

public class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {

  private final DateTimeFormatter format = DateTimeFormatter.ISO_DATE_TIME;

  @Override
  public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
    gen.writeString(value.format(format));
  }
  
}

And deserialization:

public class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {

  private final DateTimeFormatter fmt = DateTimeFormatter.ISO_DATE_TIME;

  @Override
  public LocalDateTime deserialize(JsonParser p, DeserializationContext context) throws IOException {
    return LocalDateTime.parse(p.getValueAsString(), fmt);
  }
  
}
like image 33
Artegon Avatar answered Oct 14 '22 18:10

Artegon