Deserializing LocalDateTime with Jackson JSR310 module

Mekswoll picture Mekswoll · Apr 11, 2015 · Viewed 40.6k times · Source

I'm using the library described the Jackson Datatype JSR310 page but I'm still having difficulty getting it to work.

I have configured the following bean:

@Bean
@Primary
public ObjectMapper objectMapper() {
    ObjectMapper mapper = new ObjectMapper();
    mapper.registerModule(new JSR310Module());
    return mapper;
}

When I call my REST API the date format output is yyyy-MM-dd'T'HH:ss.SSSSSS, e.g. 2015-04-11T00:10:38.905847. This gets handled by my AngularJS code just fine.

When I want to submit something to the REST API the date is posted as yyyy-MM-dd'T'HH:mm:ss.SSS'Z', e.g. 2015-04-09T08:30:00.000Z

Jackson keeps complaining about the 'Z' at the end. If I look at the LocalDateTimeDeserializer in the documentation it uses the DateTimeFormatter.ISO_LOCAL_DATE_TIME which boils to ISO_LOCAL_DATE'T'ISO_LOCAL_TIME and it mentions it has no override zone.

So I figured I should set the DateFormat on the ObjectMapper I'm creating:

@Bean
@Primary
public ObjectMapper objectMapper() {
    ObjectMapper mapper = new ObjectMapper();
    mapper.registerModule(new JSR310Module());
    mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"));
    return mapper;
}

But this does nothing. I changed it to something simple like yyyy-MM-dd but the serialized date remained in the previous format and the deserialization isn't affected either.

What am I doing wrong here to get this to work? The date format in my JavaScript code is, as far as I know the ISO 8601 format...

Answer

user1299153 picture user1299153 · Nov 5, 2015

It's not necessary to write your own serializer. It's enough use the default one, but making an instance with another format (the time_zone one) so that the exceeding part is just cut:

new LocalDateTimeDeserializer(DateTimeFormatter.ISO_DATE_TIME)

In my case I've got a contextResolver like this to achieve at configuration level:

@Service 
@Provider
public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper> {  
    private final ObjectMapper mapper;

    public ObjectMapperContextResolver() {
        mapper = new ObjectMapper();
        JavaTimeModule javaTimeModule=new JavaTimeModule();
        // Hack time module to allow 'Z' at the end of string (i.e. javascript json's) 
        javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ISO_DATE_TIME));
        mapper.registerModule(javaTimeModule);
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    }

    @Override
    public ObjectMapper getContext(Class<?> type) {
        return mapper;
    }  
}