使用 Gson 反序列化不可变列表

2022-09-04 08:06:01

我正在使用相当多的不可变集合,我很好奇如何使用Gson反序列化它们。由于没有人回答,我自己也找到了解决方案,所以我正在简化问题并提出自己的答案。

我有两个问题:

  • 如何为所有人写一个单一的工作?DeserializerImmutableList<XXX>
  • 如何注册所有人?ImmutableList<XXX>

答案 1

更新:有 https://github.com/acebaggins/gson-serializers 涵盖了许多番石榴系列:

  • ImmutableList
  • ImmutableSet
  • ImmutableSortedSet
  • ImmutableMap
  • ImmutableSortedMap

如何编写一个适用于所有不可变列表的解串器?

这个想法很简单,将传递的表示 a 转换为表示,使用内置的功能创建一个并将其转换为 .TypeImmutableList<T>TypeList<T>GsonListImmutableList

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);
    }
}

我使用的Java库中有多个类,但没有一个用于公共用途。我用.ParameterizedTypeImplsun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl

如何为所有不可变列表注册它?

这部分是微不足道的,注册的第一个参数是误导我使用,其中简单地使用就可以完成工作:java.lang.reflect.TypeParameterizedTypeClass

final Gson gson = new GsonBuilder()
    .registerTypeAdapter(ImmutableList.class, myJsonDeserializer)
    .create();

答案 2

另一个没有参数化类型的实现简单明了

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