GSON と LocalDate / LocalDateTime のシリアライズ・デシリアライズ

Java7をやめてJava8で開発するようになり、java.util.Dateを使わなくなり、

Google gson で LocalDate / LocalDateTime をシリアライズ・デシリアライズするのに

簡単に書ける方法を探すのに苦労したのでその過程と結果です。

GsonBuilder の registerTypeAdapter で LocalDateのシリアライズ&デシリアライズ

LocalDateTimeのシリアライズ&デシリアライズと、registerTypeAdapter の呼び出しを4回も書かなくてはならない。

  new GsonBuilder().registerTypeAdapter(LocalDate.class, new JsonSerializer<LocalDate>(){

            @Override
              public JsonElement serialize(LocalDate date, Type type, JsonSerializationContext context){
                  return new JsonPrimitive(date.format(DateTimeFormatter.ofPattern("yyyy/MM/dd")));
              }
          }).  /* このようなものを、毎回4つ書くのは辛い。。*/

そこで、以下のような Adapter を2つ用意する。

 

@FunctionalInterface
public interface LocalDateAdapter extends JsonSerializer<LocalDate>, JsonDeserializer<LocalDate> {
@Override
public default JsonElement serialize(LocalDate date, Type type, JsonSerializationContext context){

return new JsonPrimitive(date.format(getFormatter()));
}
@Override
public default LocalDate deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException{

return LocalDate.parse(json.getAsString(), getFormatter());
}

public static LocalDateAdapter create(LocalDateAdapter a){
return a;
}

public DateTimeFormatter getFormatter();

}

@FunctionalInterface
public interface LocalDateTimeAdapter extends JsonSerializer<LocalDateTime>, JsonDeserializer<LocalDateTime> {
@Override
public default JsonElement serialize(LocalDateTime datetime, Type type, JsonSerializationContext context){
return new JsonPrimitive(datetime.format(getFormatter()));
}
@Override
public default LocalDateTime deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException{
return LocalDateTime.parse(json.getAsString(), getFormatter());
}
public static LocalDateTimeAdapter create(LocalDateTimeAdapter a){
return a;
}
public DateTimeFormatter getFormatter();
}

========================

こうすると。。。

Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation()
.registerTypeAdapter(LocalDate.class, LocalDateAdapter.create(()->DateTimeFormatter.ofPattern("yyyy/MM/dd")))
.registerTypeAdapter(LocalDateTime.class, LocalDateTimeAdapter.create(()->DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss.SSS")))
.create();

と日付時刻のフォーマッタを指定する呼び出しとして書くことができる。