如何使用动态类型反序列化 JSON 字段?
How to deserialize JSON field with dynamic type?
在对 Reddit API 的请求中,有一个与每个 post 关联的字段称为 edited
。该字段具有 boolean
值,或者如果 post 已被编辑,则具有 long
值,我认为这是编辑 post 时的时间戳。如何在不知道类型的情况下使用 GSON 反序列化 ?如果我尝试反序列化为 Boolean
值,如果存在时间戳,我会得到一个异常。
JSON 回复的下图:
用 @JsonAdapter
注释动态字段可能是解决此问题的最简单方法(假设您有 DTO class):
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);
}
}
}
上面的类型适配器非常自我描述。当然,它可以以更通用的方式实现,但超出了这里的范围。此外,请注意它不会选择可以在 GsonBuilder
中重新配置的原始 Long
类型适配器。使用示例:
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
在对 Reddit API 的请求中,有一个与每个 post 关联的字段称为 edited
。该字段具有 boolean
值,或者如果 post 已被编辑,则具有 long
值,我认为这是编辑 post 时的时间戳。如何在不知道类型的情况下使用 GSON 反序列化 ?如果我尝试反序列化为 Boolean
值,如果存在时间戳,我会得到一个异常。
JSON 回复的下图:
用 @JsonAdapter
注释动态字段可能是解决此问题的最简单方法(假设您有 DTO class):
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);
}
}
}
上面的类型适配器非常自我描述。当然,它可以以更通用的方式实现,但超出了这里的范围。此外,请注意它不会选择可以在 GsonBuilder
中重新配置的原始 Long
类型适配器。使用示例:
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