[Spring Boot] JacksonでLocalDateをjson <-> オブジェクトに変換
Jackson で Java8 以降に追加された LocalDate 型のフィールドを持つオブジェクトと json を変換する際の、シリアライズ・デシリアライズの方法。
Contents
現象
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
型の変換は下記に記載。