你能直接将ISO 8601时间戳映射到OffsetDateTime或ZonedDateTime与Retrofit 2和Gson吗?

时间:2017-01-05 13:17:03

标签: java android gson retrofit2 threetenbp

在Android上,使用 Retrofit 2 及其 Gson转换器,您可以映射 ISO 8601字符串如"2016-10-26T11:36:29.742+03:00"(在后端的JSON响应中)直接进入POJO中的java.util.Date字段。这很好地开箱即用。

现在,我正在使用ThreeTenABP lib(它提供了后端版本的java.time类),我想知道是否可以将ISO时间戳字符串直接映射到更好的,更多现代类型,例如OffsetDateTimeZonedDateTime

在大多数情况下(想想服务器端的Java 8),显然,从“2016-10-26T11:36:29.742+03:00”到OffsetDateTimeZonedDateTime的转换很简单,由于日期字符串包含时区信息。

我尝试在我的POJO中使用OffsetDateTimeZonedDateTime(而不是日期),但至少开箱即用它不起作用。如果你能在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 个答案:

答案 0 :(得分:3)

你可以:

  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. 将Gson模型类中的ThreeTen类型与Retrofit一起使用。

  5. 同样,如果要将ThreeTen类型序列化为JSON,还要在类型适配器中实现JsonSerializer

答案 1 :(得分:1)

我创建了一个小型图书馆,完全符合laalto在答案中提出的建议,随时可以使用它:Android Java Time Gson Deserializers