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.

September 23, 2014

Java 8 LocalDate with Jackson Serialize and Deserialize Example - RESTful WS

Although I having using Joda Time for years, it is now time to migrate over to the Java 8 Date and Time API (JSR310), and make use of the new LocalDate and LocalTime classes.

WildFly 8.1.0 uses Jackson 2.3.2 which does not know how to (de)serialize the JSR310 Date Time classes. So in order to use the Date and Time API we need to add a Jackson third party datatype dependency to our pom:
<dependency>
    <groupid>com.fasterxml.jackson.datatype</groupid>
    <artifactid>jackson-datatype-jsr310</artifactid>
    <version>2.4.0</version>
</dependency>
Then to deserialize your LocalDate add the @JsonDeserialize annotation and use the LocalDateDeserializer:
@Path("/resource")
@Produces("application/json")
public class MyRestResource {

    @GET
    @Path("now")
    @JsonDeserialize(using = LocalDateDeserializer.class)
    public LocalDate get() {
        return LocalDate.now();
    }
}
To serialize your LocalDate add @JsonSerialize annotation and use the LocalDateSerializer:
@JsonSerialize(using = LocalDateSerializer.class)

To create your own serializer/deserializer check this example, which shows you how you can format the date.