[Spring Boot] JacksonでLocalDateをjson <-> オブジェクトに変換

2021-07-18JavaSpringBoot

Jackson で Java8 以降に追加された LocalDate 型のフィールドを持つオブジェクトと json を変換する際の、シリアライズ・デシリアライズの方法。

現象

SpringBoot で RestController を使うと、 json とオブジェクトは Jackson を使って変換される。
オブジェクトに Java8 以降に追加された LocalDate 型のフィールドを持つ場合、何もしないで json 変換すると以下のようになる。

LocalDate 型のフィールドを持つオブジェクト

@Data
public class User {
    private LocalDate date;
}

変換処理

ObjectMapper objectMapper = new ObjectMapper();

// オブジェクト -> json 変換
User obj = new User();
obj.setDate(LocalDate.now());
String json = objectMapper.writeValueAsString(obj);
System.out.println("オブジェクト--->JSON: "+json);

// json ->オブジェクト 変換
String json1 = "{\"date\":\"2020-09-19\"}";
System.out.println("JSON--->オブジェクト: "+objectMapper.readValue(json1, User.class));

オブジェクト -> json 変換

LocalDate 型を json に変換すると chronology とかたくさんの情報が付与される。

{"date":{
"year":2021,
"month":"JULY",
"era":"CE",
"dayOfYear":199,
"dayOfWeek":"SUNDAY",
"leapYear":false,
"monthValue":7,
"dayOfMonth":18,
"chronology":{"id":"ISO","calendarType":"iso8601"}
}}

json ->オブジェクト 変換

エラー発生

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: 
Cannot construct instance of `java.time.LocalDate` (no Creators, like default constructor, exist): no String-argument constructor/factory method to deserialize from String value ('2020-09-19')

対応

オブジェクト -> json 変換

シリアライズしてくれるアノテーションと、フォーマットしてくれるアノテーションを付与する。

@JsonSerialize(using = LocalDateSerializer.class)
@JsonFormat(pattern = "yyyy-MM-dd")

json ->オブジェクト 変換

デシリアライズしてくれるアノテーションを付与する。

@JsonDeserialize(using = LocalDateDeserializer.class)

LocalDate 型のフィールドを持つオブジェクトにアノテーション付与

import java.time.LocalDate;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;

import lombok.Data;

@Data
public class User {

    @JsonDeserialize(using = LocalDateDeserializer.class)
    @JsonSerialize(using = LocalDateSerializer.class)
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate date;
}

JsonSerialize JsonDeserialize  アノテーションには、com.fasterxml.jackson.datatype が持つ LocalDateSerializer クラスと LocalDateDeserializer クラスを使っているが、カスタムのシリアライザー、デシリアライザークラスを作って使うこともできる。
13. Custom Date Deserializer

ZonedDateTime 型の変換は下記に記載。

Posted by Agopeanuts