Можете ли вы напрямую отобразить временные метки ISO 8601 в OffsetDateTime или ZonedDateTime с помощью Retrofit 2 и Gson?

На Android, используя Retrofit 2 и его конвертер Gson, вы можете отобразить строки ISO 8601 как "2016-10-26T11:36:29.742+03:00" (в ответе JSON бэкэнда) непосредственно в java.util.Date поля в POJO. Это работает аккуратно из коробки.

Теперь я использую библиотеку ThreeTenABP (в ней представлены версии классов java.time с обратным портированием), и мне было интересно, можно ли напрямую отобразить строки меток времени ISO в более красивый, более современный тип, такой как OffsetDateTime или же ZonedDateTime,

В большинстве случаев (например, Java 8 на стороне сервера), очевидно, преобразование из2016-10-26T11:36:29.742+03:00В OffsetDateTime или же ZonedDateTime было бы просто, так как строка даты включает информацию о часовом поясе.

Я пытался использовать оба OffsetDateTime а также ZonedDateTime (вместо даты) в моих POJO, но по крайней мере из коробки это не работает. Есть идеи, если вы можете сделать это на Android с Retrofit 2?

зависимости:

compile 'com.squareup.retrofit2:retrofit:2.0.2'
compile 'com.squareup.retrofit2:converter-gson:2.0.2'

compile 'com.jakewharton.threetenabp:threetenabp:1.0.4'

Сборка экземпляра Retrofit:

new Retrofit.Builder()
// ...
.addConverterFactory(GsonConverterFactory.create())
.build();

2 ответа

Решение

Вы можете:

  1. Создайте адаптер типа, который реализует JsonDeserializer<T> и преобразует литералы JSON в любые типы ThreeTen, которые вы хотите. Пример для LocalDate:

    @Override
    public LocalDate deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        try {
            if (typeOfT == LocalDate.class) {
                return LocalDate.parse(json.getAsJsonPrimitive().getAsString(), DateTimeFormatter.ISO_DATE);
            }
        } catch (DateTimeParseException e) {
            throw new JsonParseException(e);
        }
        throw new IllegalArgumentException("unknown type: " + typeOfT);
    }
    

    Реализация подобных для типов ThreeTen, которые вы хотите, оставлена ​​в качестве упражнения.

  2. Зарегистрируйте адаптер типа на GsonBuilder при строительстве Gson пример:

    GsonBuilder gsonBuilder = new GsonBuilder();
    gsonBuilder.registerTypeAdapter(LocalDate.class, new YourTypeAdapter());
    Gson gson = gsonBuilder.create();
    
  3. Зарегистрировать Gson экземпляр с Retrofit.Builder:

    builder.addConverterFactory(GsonConverterFactory.create(gson));
    
  4. Используйте типы ThreeTen в ваших классах моделей Gson с Retrofit.

Точно так же, если вы хотите сериализовать типы ThreeTen в JSON, также реализуйте JsonSerializer в вашем типе адаптера.

Я создал небольшую библиотеку, которая делает именно то, что предлагает laalto в своем ответе, не стесняйтесь ее использовать: Android Java Time Gson Deserializer

Другие вопросы по тегам