😎

long値のミリ秒をLocalDateTimeにデシリアライズする

2023/02/11に公開

概要

RestTemplateでAPIをコールして得られる返戻値は時刻をミリ秒で扱ってるが、
プログラム中ではLocalDateTimeで扱いたい場合に、デシリアライズのタイミングで変換させる実装

前提

デシリアライズしたいjson

{
  "eventTime":1676101633075
}
Event.class
public class Event {
    LocalDateTime eventTime;
}

javaでjson文字列をデシリアライズする際、jacksonobjectMapperを使うことが多いと思われますが、上記のままだとデシリアライズがうまくいきません。

Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Java 8 date/time type `java.time.LocalDateTime` not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling
 at [Source: (String)"{ "eventTime" : 1676101633075 }"; line: 1, column: 17] (through reference chain: org.example.Event["eventTime"])

デシリアライザーを実装する

StdDeserializerを継承したカスタムデシリアライザーを実装し、eventTimeフィールドのデシリアライザーとして設定することで、ミリ秒の時刻をそのままLocalDateTimeとして、デシリアライズすることができます。
https://fasterxml.github.io/jackson-databind/javadoc/2.7/com/fasterxml/jackson/databind/deser/std/StdDeserializer.html

LocalDateTimeDeserializer.class
public class LocalDateTimeDeserializer extends StdDeserializer<LocalDateTime> {

    protected LocalDateTimeDeserializer(){
        super (LocalDateTime.class);
    }

    @Override
    public  LocalDateTime deserialize(JsonParser p , DeserializationContext ctxt) throws IOException{
        final long epochmillis = p.readValueAs(Long.class);
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(epochmillis), ZoneId.systemDefault());
    }
}
Event.class
public class Event {
  // 実装したカスタムデシリアライザーを設定
    @JsonDeserialize(using = LocalDateTimeDeserializer.class)
    LocalDateTime eventTime;
}
Main.class
public class Main {
    public static void main(String[] args)  throws  Exception{
        String jsonEvent = "{ \"eventTime\" : 1676101633075 }";
        Event event = new ObjectMapper().readValue(jsonEvent, Event.class);
        System.out.println("eventTime is " + event.getEventTime());
	// eventTime is 2023-02-11T16:47:13.075
    }
}

↑例外が発生せず、ミリ秒・long型の時刻をLocalDateTimeにデシリアライズすることができました。

Discussion