carlosjai.me

Tip: [Java / REST] Creating a Jackson multi date format deserializer.

In a microservice that is used by several portals, I have found the need that in certain endpoints, the dates received in the JSON of the requests can have different formats.
This is a problem since the Jackson @JsonFormat tag only allows us to declare a single pattern, like:

	@JsonFormat(pattern = "yyyy-MM-dd")
	private LocalDate incidentDate;

Luckily, there is another tag that allows us to carry out this development: @JsonDeserialize.

	@JsonDeserialize(using = MultiDateDeserializer.class)
	private LocalDate incidentDate;

A@JsonDeserialize allows us to specify a class that will perform custom deserialization. This is very useful in cases like this, where we need to perform additional steps in our requests.

package me.carlosjai.example.utils;

import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Arrays;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import org.apache.commons.lang3.StringUtils;

import static me.carlosjai.example.utils.DateFormats.INTERNATIONAL_DATE_FORMATS;

public class MultiDateDeserializer extends StdDeserializer<LocalDate> {
	private static final long serialVersionUID = 1L;

	public MultiDateDeserializer() {
		this(null);
	}

	public MultiDateDeserializer(Class<?> vc) {
		super(vc);
	}

	@Override
	/**
	 * Deserializes a custom date in several international date formats
	 */
	public LocalDate deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
		final String date =((JsonNode)jp.getCodec().readTree(jp)).textValue();
		if(date== null || StringUtils.isBlank(date)) {
			return null;
		}
		for (String dateFormat : INTERNATIONAL_DATE_FORMATS) {
			try {
				return LocalDate.parse(date, DateTimeFormatter.ofPattern(dateFormat));
			} catch (DateTimeParseException e) {
			}
		}
		throw new JsonParseException(jp, "Unparseable date: \"" + date + "\". Supported formats: " + Arrays.toString(INTERNATIONAL_DATE_FORMATS));
	}
}

And the DateFormats class:

package me.carlosjai.example.utils;

public class DateFormats {
	public static final String LITHUANIA_DATE_FORMAT = "yyyy-MM-dd";
	public static final String LATVIA_DATE_FORMAT = "dd.MM.yyyy.";
	public static final String[] INTERNATIONAL_DATE_FORMATS = new String[] {
		LITHUANIA_DATE_FORMAT,
		LATVIA_DATE_FORMAT,
	};
}

And… Its done!

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.