Как десериализовать поле JSON с динамическим типом? - PullRequest
0 голосов
/ 24 мая 2018

В запросе к Reddit API есть поле, связанное с каждым сообщением, которое называется edited.Это поле либо имеет значение boolean, либо, если сообщение было отредактировано, имеет значение long, которое, я думаю, является отметкой времени, когда сообщение было отредактировано.Как я могу десериализовать это с GSON без , зная тип?Если я пытаюсь десериализовать в значение Boolean, я получаю исключение при наличии временной отметки.

Изображение ниже ответа JSON:

JSON response

1 Ответ

0 голосов
/ 24 мая 2018

Обозначение динамического поля с помощью @JsonAdapter, вероятно, самый простой способ обойти это (при условии, что у вас есть класс DTO):

final class Datum {

    @JsonAdapter(MaybeLongTypeAdapter.class)
    final Long edited = null;

}

Где MaybeLongTypeAdapter выглядит следующим образом:

final class MaybeLongTypeAdapter
        extends TypeAdapter<Long> {

    private MaybeLongTypeAdapter() {
    }

    @Override
    public void write(final JsonWriter out, final Long value) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Long read(final JsonReader in)
            throws IOException {
        switch ( in.peek() ) {
        case NULL:
            return null;
        case BOOLEAN:
            if ( in.nextBoolean() ) {
                throw new JsonSyntaxException("Unexpected `true` at " + in);
            }
            return null;
        case NUMBER:
            return in.nextLong();
        default:
            throw new JsonSyntaxException("Unexpected element at " + in);
        }
    }

}

Адаптер типа выше довольно информативен.Конечно, он может быть реализован более общим способом, но здесь он выходит за рамки.Кроме того, обратите внимание, что он не выбирает оригинальный адаптер типа Long, который можно переконфигурировать в GsonBuilder.Пример использования:

private static final Gson gson = new Gson();

private static final Type listOfDatumType = new TypeToken<List<Datum>>() {}.getType();

public static void main(final String... args) {
    final String json = "[{\"edited\": false},{\"edited\": 1527130582}]";
    final List<Datum> data = gson.fromJson(json, listOfDatumType);
    for ( final Datum datum : data ) {
        System.out.println(datum.edited);
    }
}

Выход:

null
1527130582

...