编辑:它看起来像在这种情况下,有一个更容易的解决这个问题,即通过注册多集的instance creator方式:
private static class MultisetInstanceCreator implements InstanceCreator<Multiset<?>> {
@Override
public Multiset<?> createInstance(Type type) {
return HashMultiset.create();
}
}
Gson gson = new GsonBuilder()
.registerTypeAdapter(Multiset.class, new MultisetInstanceCreator())
.create();
的实例创建者只定义一个多重应该如何创建,因为Guava集合没有默认的构造函数(无论如何,Multiset都是接口)。
原来的答复:我不知道这是否是达到你想要什么是最好的或最简单的方法,但它是最近对我们工作了一个类似的问题的一种方法(在我们的情况下,它是deserialising到一个ImmutableMap)。
其基本思想是注册一个custom deserialiser,它基本上做了你已经发现的一个可能的解决方案:将数据反序列化到一个ArrayList,然后把它变成一个Multiset。这样做的好处是你只需要注册一次自定义的反序列化器,而不必到处都知道首先使用ArrayList类型。
这种定制解串器看起来是这样的:
private static class MultisetDeserializer implements JsonDeserializer<Multiset<?>> {
@Override
public Multiset<?> deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {
ParameterizedType parameterizedType = (ParameterizedType) type;
Type[] typeArguments = parameterizedType.getActualTypeArguments();
ParameterizedType listType = new ListParameterizedType(typeArguments);
List<?> list = context.deserialize(json, listType);
return HashMultiset.create(list);
}
}
总之,这蒙上预期的类型deserialise到(例如,在你的情况new TypeToken<Multiset<String>>(){}.getType()
),以ParameterizedType
的类型参数(在你的例子字符串),以获得。然后它创建一个新的ParameterizedType,它是具有相同类型参数的ArrayList类型(如下所示)。使用上下文将JSON反序列化为这种新类型之后,您只需致电HashMultiset.create
即可。
的ListParameterizedType
看起来是这样的:
private static class ListParameterizedType implements ParameterizedType {
private final Type[] typeArguments;
private ListParameterizedType(Type[] typeArguments) {
this.typeArguments = typeArguments;
}
@Override
public Type[] getActualTypeArguments() {
return typeArguments;
}
@Override
public Type getRawType() {
return ArrayList.class;
}
@Override
public Type getOwnerType() {
return null;
}
}
请注意,您可以用几乎这里的任何列表类取代ArrayList
,只要它有一个类型参数的默认的构造。
也可能有更简单的方法来实现同样的事情,例如,您可以通过检查JsonElement
的方法(如isJsonArray()
)手动执行一些解析。这可以帮助您避免创建一个ArrayList,之后立即抛弃它。
这实际上就是我所做的(虽然代码不够整齐)。 –
@ChthonicProject查看我的更新答案,事实证明这比我想象的要容易得多,因为你需要做的就是定义如何创建一个Multiset。 – andersschuller