Deserializing ImmutableList using Gson

后端 未结 3 1703
自闭症患者
自闭症患者 2020-12-10 03:49

I\'m using quite a few immutable collections and I\'m curious how to deserialize them using Gson. As nobody answered and I\'ve found the solution myself, I\'m simplifying th

相关标签:
3条回答
  • 2020-12-10 04:29

    One more implementation without 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);
    }
    
    0 讨论(0)
  • 2020-12-10 04:30

    Update: There's https://github.com/acebaggins/gson-serializers which covers many guava collections:

    • ImmutableList
    • ImmutableSet
    • ImmutableSortedSet
    • ImmutableMap
    • ImmutableSortedMap

    How to write a single Deserializer working for all 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.

    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. I tested it with sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl.

    How to register it for all 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:

    final Gson gson = new GsonBuilder()
        .registerTypeAdapter(ImmutableList.class, myJsonDeserializer)
        .create();
    
    0 讨论(0)
  • 2020-12-10 04:51

    @maaartinus already covered the second question, so I'll post a complementary Guava-based solution to the first question which doesn't require 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));   
      }
    }
    
    0 讨论(0)
提交回复
热议问题