It's not that straightforward, since you would want to maintain the type parameters in order to build a map containing the right types. To do that, you can go with a TypeAdapterFactory
, and ask there for a delegate TypeAdapter
, using the fully specified TypeToken
.
public class ImmutableMapTypeAdapterFactory implements TypeAdapterFactory {
public static final ImmutableMapTypeAdapterFactory INSTANCE = new ImmutableMapTypeAdapterFactory();
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
if (!ImmutableMap.class.isAssignableFrom(type.getRawType())) {
return null;
}
final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);
return new TypeAdapter<T>() {
@Override
public void write(JsonWriter out, T value) throws IOException {
delegate.write(out, value);
}
@Override
@SuppressWarnings("unchecked")
public T read(JsonReader in) throws IOException {
return (T) ImmutableMap.copyOf((Map) delegate.read(in));
}
};
}
}
Now you have another problem: the default GSON MapTypeAdapterFactory
will try to create an instance of ImmutableMap
, and modify it. This obviously won't work. You should create a TypeToken<HashMap<K, V>>
from the TypeToken<ImmutableMap<K, V>>
, but I honestly don't know how you can do that. Instead, you can use an InstanceCreator
to trick GSON into building a HashMap
when an ImmutableMap
is actually required:
public static <K,V> InstanceCreator<Map<K, V>> newCreator() {
return new InstanceCreator<Map<K, V>>() {
@Override
public Map<K, V> createInstance(Type type) {
return new HashMap<K, V>();
}
};
}
Clearly you have to register both the TypeAdapterFactory and the InstanceCreator:
GsonBuilder b = new GsonBuilder();
b.registerTypeAdapterFactory(new ImmutableMapTypeAdapterFactory());
b.registerTypeAdapter(ImmutableMap.class, ImmutableMapTypeAdapterFactory.newCreator());
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…