Сериализовать Java 8 LocalDate как yyyy-mm-dd с помощью Gson

Я использую Java 8 и последнюю версию RELEASE (через Maven) Gson. Если я сериализую LocalDate я получаю что-то вроде этого

"birthday": {
        "year": 1997,
        "month": 11,
        "day": 25
}

где я бы предпочел "birthday": "1997-11-25". Поддерживает ли Gson более сжатый формат из коробки, или мне нужно реализовать собственный сериализатор для LocalDate s?

(Я пробовал gsonBuilder.setDateFormat(DateFormat.SHORT), но это, похоже, не имеет значения.)

Ответ 1

До дальнейшего уведомления я внедрил собственный сериализатор:

class LocalDateAdapter implements JsonSerializer<LocalDate> {

    public JsonElement serialize(LocalDate date, Type typeOfSrc, JsonSerializationContext context) {
        return new JsonPrimitive(date.format(DateTimeFormatter.ISO_LOCAL_DATE)); // "yyyy-mm-dd"
    }
}

Он может быть установлен, например, так:

Gson gson = new GsonBuilder()
        .setPrettyPrinting()
        .registerTypeAdapter(LocalDate.class, new LocalDateAdapter())
        .create();

Ответ 2

Я использую следующее, поддерживает чтение/запись и нулевые значения:

class LocalDateAdapter extends TypeAdapter<LocalDate> {
    @Override
    public void write(final JsonWriter jsonWriter, final LocalDate localDate) throws IOException {
        if (localDate == null) {
            jsonWriter.nullValue();
        } else {
            jsonWriter.value(localDate.toString());
        }
    }

    @Override
    public LocalDate read(final JsonReader jsonReader) throws IOException {
        if (jsonReader.peek() == JsonToken.NULL) {
            jsonReader.nextNull();
            return null;
        } else {
            return LocalDate.parse(jsonReader.nextString());
        }
    }
}

Зарегистрированный как @Drux говорит:

return new GsonBuilder()
        .registerTypeAdapter(LocalDate.class, new LocalDateAdapter())
        .create();

РЕДАКТИРОВАТЬ 2019-04-04 Упрощенная реализация

private static final class LocalDateAdapter extends TypeAdapter<LocalDate> {
    @Override
    public void write( final JsonWriter jsonWriter, final LocalDate localDate ) throws IOException {
        jsonWriter.value(localDate.toString());
    }

    @Override
    public LocalDate read( final JsonReader jsonReader ) throws IOException {
        return LocalDate.parse(jsonReader.nextString());
    }
}

К которой вы можете добавить поддержку null, зарегистрировав упакованную версию nullSafe():

new GsonBuilder()
      .registerTypeAdapter(LocalDate.class, new LocalDateAdapter().nullSafe())

Ответ 3

Версия Kotlin, поддерживающая сериализацию и десериализацию:

class LocalDateTypeAdapter : TypeAdapter<LocalDate>() {

    override fun write(out: JsonWriter, value: LocalDate) {
        out.value(DateTimeFormatter.ISO_LOCAL_DATE.format(value))
    }

    override fun read(input: JsonReader): LocalDate = LocalDate.parse(input.nextString())
}

Зарегистрируйтесь в вашем GsonBuilder. Оберните, используя nullSafe() для поддержки null:

GsonBuilder().registerTypeAdapter(LocalDate::class.java, LocalDateTypeAdapter().nullSafe())