[英]Deserializing ImmutableList using Gson
I'm using quite a few immutable collections and I'm curious how to deserialize them using Gson. 我正在使用许多不可变的集合,并且很好奇如何使用Gson反序列化它们。 As nobody answered and I've found the solution myself, I'm simplifying the question and presenting my own answer.
由于没有人回答,而且我自己找到了解决方案,因此我正在简化问题并提出自己的答案。
I had two problems: 我有两个问题:
Deserializer
working for all ImmutableList<XXX>
? ImmutableList<XXX>
的单个Deserializer
? ImmutableList<XXX>
? ImmutableList<XXX>
注册它? Update: There's https://github.com/acebaggins/gson-serializers which covers many guava collections: 更新:有https://github.com/acebaggins/gson-serializers ,其中涵盖了许多番石榴集合:
ImmutableList
ImmutableSet
ImmutableSortedSet
ImmutableMap
ImmutableSortedMap
How to write a single Deserializer working for all ImmutableList?
如何编写适用于所有ImmutableList的单个反序列化器?
The idea is simple, transform the passed Type
representing an ImmutableList<T>
into a Type
representing List<T>
, use the build-in Gson
's capability to create a List
and convert it to an ImmutableList
. 这个想法是简单,变换传递
Type
表示ImmutableList<T>
成Type
表示List<T>
中,使用内置的Gson
的能力来创建List
并将其转换为一个ImmutableList
。
class MyJsonDeserializer implements JsonDeserializer<ImmutableList<?>> {
@Override
public ImmutableList<?> deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {
final Type type2 = ParameterizedTypeImpl.make(List.class, ((ParameterizedType) type).getActualTypeArguments(), null);
final List<?> list = context.deserialize(json, type2);
return ImmutableList.copyOf(list);
}
}
There are multiple ParameterizedTypeImpl
classes in Java libraries I use, but none of them intended for public usage. 我使用的Java库中有多个
ParameterizedTypeImpl
类,但是它们都不适合公共使用。 I tested it with sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
. 我使用
sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
测试了它。
How to register it for all ImmutableList?
如何为所有ImmutableList注册它?
That part is trivial, the first argument to register is java.lang.reflect.Type
which mislead me to using ParameterizedType
, where simply using Class
does the job: 这部分很简单,register的第一个参数是
java.lang.reflect.Type
,它使我误以为使用ParameterizedType
,而仅使用Class
完成工作:
final Gson gson = new GsonBuilder()
.registerTypeAdapter(ImmutableList.class, myJsonDeserializer)
.create();
One more implementation without ParameterizedTypeImpl 没有ParameterizedTypeImpl的另一种实现
@Override
public ImmutableList<?> deserialize(final JsonElement json, final Type type, final JsonDeserializationContext context) throws JsonParseException {
@SuppressWarnings("unchecked")
final TypeToken<ImmutableList<?>> immutableListToken = (TypeToken<ImmutableList<?>>) TypeToken.of(type);
final TypeToken<? super ImmutableList<?>> listToken = immutableListToken.getSupertype(List.class);
final List<?> list = context.deserialize(json, listToken.getType());
return ImmutableList.copyOf(list);
}
@maaartinus already covered the second question, so I'll post a complementary Guava-based solution to the first question which doesn't require ParametrizedTypeImpl
@maaartinus已经讨论了第二个问题,因此我将为第一个问题发布一个基于番石榴的补充解决方案,该解决方案不需要
ParametrizedTypeImpl
public final class ImmutableListDeserializer implements JsonDeserializer<ImmutableList<?>> {
@Override
public ImmutableList<?> deserialize(final JsonElement json, final Type type,
final JsonDeserializationContext context)
throws JsonParseException {
final Type[] typeArguments = ((ParameterizedType) type).getActualTypeArguments();
final Type parameterizedType = listOf(typeArguments[0]).getType();
final List<?> list = context.deserialize(json, parameterizedType);
return ImmutableList.copyOf(list);
}
private static <E> TypeToken<List<E>> listOf(final Type arg) {
return new TypeToken<List<E>>() {}
.where(new TypeParameter<E>() {}, (TypeToken<E>) TypeToken.of(arg));
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.