You can tell how to configure ObjectMapper to automatically handle LocalDateTime
class covered here:
serialize/deserialize java 8 java.time with Jackson JSON mapper
But when I try to use POJOs with java.time
objects, Jersey fails to parse them with errors:
Java 8 date/time type `java.time.LocalDateTime` not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling
But I do have that Maven dependency added.
How do you configure Jersey HTTP clients so that it uses ObjectMapper with the JavaTimeModule added when serializing json to objects?
You need to use the register method on the javax.ws.rs.client.Client
to register a provider that can automatically convert using ObjectMapper.
JerseyObjectMapperProvider.java
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import lombok.extern.slf4j.Slf4j;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
import java.io.IOException;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Objects;
@Provider
@Slf4j
public class JerseyObjectMapperProvider implements ContextResolver<ObjectMapper> {
public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
static {
OBJECT_MAPPER.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
OBJECT_MAPPER.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
OBJECT_MAPPER.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING, true);
OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(Date.class, new JsonSerializer<>() {
@Override
public void serialize(Date value, JsonGenerator gen, SerializerProvider provider) throws IOException {
provider.defaultSerializeValue(DateTimeFormatter.ISO_INSTANT.format(value.toInstant()), gen);
}
});
javaTimeModule.addSerializer(LocalDate.class,
new LocalDateSerializer(DateTimeFormatter.ISO_LOCAL_DATE));
javaTimeModule.addSerializer(LocalTime.class,
new LocalTimeSerializer(DateTimeFormatter.ISO_LOCAL_TIME));
javaTimeModule.addSerializer(LocalDateTime.class,
new LocalDateTimeSerializer(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
javaTimeModule.addDeserializer(Date.class, new JsonDeserializer<>() {
@Override
public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
if (Objects.isNull(p.getText())) {
return null;
}
return Date.from(Instant.parse(p.getText()));
}
});
javaTimeModule.addDeserializer(LocalDate.class,
new LocalDateDeserializer(DateTimeFormatter.ISO_LOCAL_DATE));
javaTimeModule.addDeserializer(LocalTime.class,
new LocalTimeDeserializer(DateTimeFormatter.ISO_LOCAL_TIME));
javaTimeModule.addDeserializer(LocalDateTime.class,
new LocalDateTimeDeserializer(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
OBJECT_MAPPER.registerModule(javaTimeModule);
SimpleModule customModule = new SimpleModule();
OBJECT_MAPPER.registerModule(customModule);
}
@Override
public ObjectMapper getContext(Class<?> type) {
return OBJECT_MAPPER;
}
}
Before using your Jersey client to access rest services, call this:
client.register(JerseyObjectMapperProvider.class);
Now you'll use the object mapper you created in the JerseyObjectMapperProvider class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With