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!