Custom Jackson Joda DateTime Deserializer

This tutorial shows how to deserialize date format when unmarshaling JSON using Jackson. The custom annotation will be created in order to pass the date format using annotation.


Below is the pom.xml file

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>roytuts</groupId>
	<artifactId>jackson</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>
	<name>jackson</name>
	<url>http://maven.apache.org</url>
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<jdk.version>1.8</jdk.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-core</artifactId>
			<version>2.9.0.pr2</version>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.datatype</groupId>
			<artifactId>jackson-datatype-joda</artifactId>
			<version>2.9.0.pr2</version>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>2.9.0.pr2</version>
			<type>jar</type>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>${jdk.version}</source>
					<target>${jdk.version}</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

Below custom annotation is used to annotate the date format.

package json;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface MyDateFormat {
	String value() default "dd/MM/yyyy";
}

The above annotation has default date format. So if you do not pass any date format while applying annotation then the default format will be applied.

Create below custom date deserializer class in order to get the desired date or datetime format from JSON to Java API.

package json;
import java.io.IOException;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
public class MyJsonDateTimeDeserializer extends JsonDeserializer<DateTime> implements ContextualDeserializer {
	private String format;
	public MyJsonDateTimeDeserializer() {
	}
	public MyJsonDateTimeDeserializer(String format) {
		this.format = format;
	}
	@Override
	public JsonDeserializer<?> createContextual(DeserializationContext dc, BeanProperty bp)
			throws JsonMappingException {
		return new MyJsonDateTimeDeserializer(bp.getAnnotation(MyDateFormat.class).value());
	}
	@Override
	public DateTime deserialize(JsonParser jp, DeserializationContext dc) throws IOException, JsonProcessingException {
		DateTimeFormatter formatter = DateTimeFormat.forPattern(format);
		DateTime dateTime = formatter.parseDateTime(jp.getText());
		return dateTime;
	}
}

In the above class joda DateTime api has been used. Also notice how annotated MyDateFormat class has been used to get the annotated value for formatting the date.

Now create below POJO class and apply the annotation on DateTime fields.

package json;
import org.joda.time.DateTime;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
public class MyPojo {
	private String name;
	@MyDateFormat("dd-MM-yyyy HH:mm:ss")
	@JsonDeserialize(using = MyJsonDateTimeDeserializer.class)
	private DateTime startDate;
	@MyDateFormat("dd-MM-yyyy")
	@JsonDeserialize(using = MyJsonDateTimeDeserializer.class)
	private DateTime endDate;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public DateTime getStartDate() {
		return startDate;
	}
	public void setStartDate(DateTime startDate) {
		this.startDate = startDate;
	}
	public DateTime getEndDate() {
		return endDate;
	}
	public void setEndDate(DateTime endDate) {
		this.endDate = endDate;
	}
	@Override
	public String toString() {
		return "MyPojo [name=" + name + ", startDate=" + startDate + ", endDate=" + endDate + "]";
	}
}

See how date format annotation has been used in the above class fields. Also see how custom Jackson date deserializer has been used in the above class.

Create below test class in order to test the custom deserializer

package json;
import java.io.IOException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JsonDateTimeSerializerDeserializerTest {
	public static void main(String[] args) throws IOException {
		ObjectMapper mapper = new ObjectMapper();
		String jsonPojo = "{\"name\":\"POJO Two\", \"startDate\":\"16-05-2017 12:00:00\", \"endDate\":\"20-05-2017\"}";
		MyPojo mp = mapper.readValue(jsonPojo, MyPojo.class);
		System.out.println(mp);
	}
}

Output

MyPojo [name=POJO Two, startDate=2017-05-16T12:00:00.000+05:30, endDate=2017-05-20T00:00:00.000+05:30]

Thanks for reading.

Leave a Reply

Your email address will not be published. Required fields are marked *