绝地无双
我找到了CollectionTypeAdapterFactory源Gson代码。我尝试修改它,它已经过测试并且很有用。public class CollectionTypeAdapterFactory implements TypeAdapterFactory { private final ConstructorConstructor constructorConstructor; public CollectionTypeAdapterFactory(ConstructorConstructor constructorConstructor) { this.constructorConstructor = constructorConstructor; } public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) { Type type = typeToken.getType(); Class<? super T> rawType = typeToken.getRawType(); if (!Collection.class.isAssignableFrom(rawType)) { return null; } Type elementType = $Gson$Types.getCollectionElementType(type, rawType); TypeAdapter<?> elementTypeAdapter = gson.getAdapter(TypeToken.get(elementType)); ObjectConstructor<T> constructor = constructorConstructor.get(typeToken); @SuppressWarnings({"unchecked", "rawtypes"}) // create() doesn't define a type parameter TypeAdapter<T> result = new Adapter(gson, elementType, elementTypeAdapter, constructor); return result; } private static final class Adapter<E> extends TypeAdapter<Collection<E>> { private final TypeAdapter<E> elementTypeAdapter; private final ObjectConstructor<? extends Collection<E>> constructor; public Adapter(Gson context, Type elementType, TypeAdapter<E> elementTypeAdapter, ObjectConstructor<? extends Collection<E>> constructor) { this.elementTypeAdapter = new TypeAdapterRuntimeTypeWrapper<E>(context, elementTypeAdapter, elementType); this.constructor = constructor; } public Collection<E> read(JsonReader in) throws IOException { if (in.peek() == JsonToken.NULL) { in.nextNull(); //In the source code is return null, I changed to return an empty collection return constructor.construct(); } Collection<E> collection = constructor.construct(); in.beginArray(); while (in.hasNext()) { E instance = elementTypeAdapter.read(in); collection.add(instance); } in.endArray(); return collection; } public void write(JsonWriter out, Collection<E> collection) throws IOException { if (collection == null) { out.nullValue(); return; } out.beginArray(); for (E element : collection) { elementTypeAdapter.write(out, element); } out.endArray(); } }}在源代码中TypeAdapterRuntimeTypeWrapper是受保护的,我们必须进行复制。 public class TypeAdapterRuntimeTypeWrapper<T> extends TypeAdapter<T> { private final Gson context; private final TypeAdapter<T> delegate; private final Type type; TypeAdapterRuntimeTypeWrapper(Gson context, TypeAdapter<T> delegate, Type type) { this.context = context; this.delegate = delegate; this.type = type; } @Override public T read(JsonReader in) throws IOException { return delegate.read(in); } @SuppressWarnings({"rawtypes", "unchecked"}) @Override public void write(JsonWriter out, T value) throws IOException { TypeAdapter chosen = delegate; Type runtimeType = getRuntimeTypeIfMoreSpecific(type, value); if (runtimeType != type) { TypeAdapter runtimeTypeAdapter = context.getAdapter(TypeToken.get(runtimeType)); if (!(runtimeTypeAdapter instanceof ReflectiveTypeAdapterFactory.Adapter)) { // The user registered a type adapter for the runtime type, so we will use that chosen = runtimeTypeAdapter; } else if (!(delegate instanceof ReflectiveTypeAdapterFactory.Adapter)) { // The user registered a type adapter for Base class, so we prefer it over the // reflective type adapter for the runtime type chosen = delegate; } else { // Use the type adapter for runtime type chosen = runtimeTypeAdapter; } } chosen.write(out, value); } private Type getRuntimeTypeIfMoreSpecific(Type type, Object value) { if (value != null && (type == Object.class || type instanceof TypeVariable<?> || type instanceof Class<?>)) { type = value.getClass(); } return type; } }如何使用Gson gson = new GsonBuilder().serializeNulls() .registerTypeAdapterFactory( new CollectionTypeAdapterFactory(new ConstructorConstructor(new HashMap<>())) ) .create();Result<List<Province>> result = gson.fromJson(jsonStr, new TypeToken<Result<List<Province>>>() {}.getType());印刷:Result{code=200, msg='success', data=[Province{id=1, name='Beijing', cities=[]}, Province{id=2, name='Guangdong', cities=[City{id=1, name='Guangzhou'}]}]}