Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to disable Jackson from deserializing an Instant from epoch millis?

I am developing an API using Spring Boot and am using Jackson for payload (de)serialization. I want to deserialize an ISO-8601 formatted datetime into a java.time.Instant, but do not want to support deserializing from epoch time in milliseconds or nanoseconds. I want to only support the data being provided to my API in one format to reduce the chance of client error.

Currently, Jackson deserializes to an Instant from both an ISO-8601 formatted string AND from a string containing only numbers e.g. "20190520".

Are there Jackson annotations I can use on my Instant field, or properties I can set to apply this kind of behaviour? Or is a custom deserializer my only option?

like image 260
Didacticus Avatar asked May 15 '19 22:05

Didacticus


1 Answers

Are there Jackson annotations I can use on my Instant field, or properties I can set to apply this kind of behaviour? Or is a custom deserializer my only option?

I am not personally aware of annotations that will do this out-of-the-box for you; but the following is a simple deserializer that does the job:

import java.io.IOException;
import java.time.Instant;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;

public class JacksonInstantDeserializer extends StdDeserializer<Instant> {
    public JacksonInstantDeserializer() { this(null); }
    public JacksonInstantDeserializer(Class<?> clazz) { super(clazz); }

    @Override
    public Instant deserialize(JsonParser parser, DeserializationContext ctx) throws IOException {
        return Instant.parse(parser.getText());
    }
}

It basically uses Instant.parse; which accepts ONLY an ISO-8601 formatted string (it will throw a DateTimeParseException if the string is not formatted accordingly) and creates an Instant based on its representation. Then you can use tell jackson to use this converter to deserialize the Instant properties of your DTOs in the following manner:

    public class MyDTO {
        @JsonDeserialize(using = JacksonInstantDeserializer.class)
        public Instant instant;
    }

Complete code on GitHub

Hope this helps.

like image 144
Marco R. Avatar answered Oct 04 '22 22:10

Marco R.