September 29, 2014

LocalDate java 8 Custom Serializer Jackson JSON Example

In this previous example we use serialize and deserialize classes provided by a Jackson third party datatype. For more control over the date formatting you can opt to create your own serialize and deserialize classes.

WildFly 8.1.0 uses Jackson 2.3.2 so we can add the following dependencies to the pom with a scope of provided:
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.4.2</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.4.2</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.4.2</version>
    <scope>provided</scope>
</dependency>
Then on the LocalDate property of your bean add the following annotations:
public class MyBean {

    @JsonDeserialize(using = JsonDateDeserializer.class)
    @JsonSerialize(using = JsonDateSerializer.class)
    private LocalDate date;
 
    public LocalDate getDate() {
        return date;
    }

    private void setDate(LocalDate date) {
        this.date = date;
    }
} 
Now create the custom JsonDateSerializer:
public class JsonDateSerializer extends JsonSerializer<LocalDate> {

    private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
 
    @Override
    public void serialize(LocalDate date, JsonGenerator generator,
            SerializerProvider provider) throws IOException,
            JsonProcessingException {

        String dateString = date.format(formatter);
        generator.writeString(dateString);
    }
}
And now the custom JsonDateDeserializer:
public class JsonDateDeserializer extends JsonDeserializer<LocalDate> {

    @Override
    public LocalDate deserialize(JsonParser jp, DeserializationContext ctxt)
            throws IOException, JsonProcessingException {

        ObjectCodec oc = jp.getCodec();
        TextNode node = (TextNode) oc.readTree(jp);
        String dateString = node.textValue();

        Instant instant = Instant.parse(dateString);
        LocalDateTime dateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
        LocalDate date = LocalDate.of(dateTime.getYear(), dateTime.getMonth(), dateTime.getDayOfMonth());
        return date;
    }
}

NOTE: The package names have changed in Jackson 2. When you use the Jackson annotations make sure you import the one from the com.fasterxml.jackson.databind.annotation.* package and not the ones from the org.codehaus.jackson.map.annotate.* package. If you import the latter, your annotations will be ignored. WildFly 8 does not load the classes from the 1.9.2 jackson module.

2 comments :

  1. Many thanks for the article! You saved me, maybe a half day of solving classpath issues :)

    ReplyDelete
    Replies
    1. Great, I think I wasted half a day trying to figure out why it was not working before learning about the new package names :)

      Delete