如何使用动态类型反序列化JSON字段?

时间:2018-05-24 05:36:14

标签: android json gson retrofit json-deserialization

在对Reddit API的请求中,每个帖子都有一个名为edited的字段。此字段具有boolean值,或者如果已编辑帖子,则具有long值,我认为该值是编辑帖子的时间戳。如何在没有知道类型的情况下使用GSON 对其进行反序列化?如果我尝试反序列化为Boolean值,如果存在时间戳,我会收到异常。

下面的JSON响应图片:

JSON response

1 个答案:

答案 0 :(得分:2)

使用@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);
    }
}

输出:

  


  1527130582