不确定这是否是您所要求的,但通过修改RuntimeTypeAdapterFactory类,我创建了一个基于Json源中条件的子类系统。
RuntimeTypeAdapterFactory.class:
package com.google.gson.typeadapters;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.internal.Streams;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
public final class RuntimeTypeAdapterFactory<T> implements TypeAdapterFactory {
private final Class<?> baseType;
private final RuntimeTypeAdapterPredicate predicate;
private final Map<String, Class<?>> labelToSubtype = new LinkedHashMap<String, Class<?>>();
private final Map<Class<?>, String> subtypeToLabel = new LinkedHashMap<Class<?>, String>();
private RuntimeTypeAdapterFactory(Class<?> baseType, RuntimeTypeAdapterPredicate predicate) {
if (predicate == null || baseType == null) {
throw new NullPointerException();
}
this.baseType = baseType;
this.predicate = predicate;
}
public static <T> RuntimeTypeAdapterFactory<T> of(Class<T> baseType, RuntimeTypeAdapterPredicate predicate) {
return new RuntimeTypeAdapterFactory<T>(baseType, predicate);
}
public static <T> RuntimeTypeAdapterFactory<T> of(Class<T> baseType) {
return new RuntimeTypeAdapterFactory<T>(baseType, null);
}
public RuntimeTypeAdapterFactory<T> registerSubtype(Class<? extends T> type, String label) {
if (type == null || label == null) {
throw new NullPointerException();
}
if (subtypeToLabel.containsKey(type) || labelToSubtype.containsKey(label)) {
throw new IllegalArgumentException("types and labels must be unique");
}
labelToSubtype.put(label, type);
subtypeToLabel.put(type, label);
return this;
}
public RuntimeTypeAdapterFactory<T> registerSubtype(Class<? extends T> type) {
return registerSubtype(type, type.getSimpleName());
}
public <R> TypeAdapter<R> create(Gson gson, TypeToken<R> type) {
if (type.getRawType() != baseType) {
return null;
}
final Map<String, TypeAdapter<?>> labelToDelegate
= new LinkedHashMap<String, TypeAdapter<?>>();
final Map<Class<?>, TypeAdapter<?>> subtypeToDelegate
= new LinkedHashMap<Class<?>, TypeAdapter<?>>();
for (Map.Entry<String, Class<?>> entry : labelToSubtype.entrySet()) {
TypeAdapter<?> delegate = gson.getDelegateAdapter(this, TypeToken.get(entry.getValue()));
labelToDelegate.put(entry.getKey(), delegate);
subtypeToDelegate.put(entry.getValue(), delegate);
}
return new TypeAdapter<R>() {
@Override public R read(JsonReader in) throws IOException {
JsonElement jsonElement = Streams.parse(in);
String label = predicate.process(jsonElement);
@SuppressWarnings("unchecked")
TypeAdapter<R> delegate = (TypeAdapter<R>) labelToDelegate.get(label);
if (delegate == null) {
throw new JsonParseException("cannot deserialize " + baseType + " subtype named "
+ label + "; did you forget to register a subtype?");
}
return delegate.fromJsonTree(jsonElement);
}
@Override public void write(JsonWriter out, R value) throws IOException {
Streams.write(null, out);
}
};
}
}
RuntimeTypeAdapterPredicate.class:
package com.google.gson.typeadapters;
import com.google.gson.JsonElement;
public abstract class RuntimeTypeAdapterPredicate {
public abstract String process(JsonElement element);
}
示例(取自我目前正在开发的项目):
ItemTypePredicate.class:
package org.libpoe.serial;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.typeadapters.RuntimeTypeAdapterPredicate;
public class ItemTypePredicate extends RuntimeTypeAdapterPredicate {
@Override
public String process(JsonElement element) {
JsonObject obj = element.getAsJsonObject();
int frameType = obj.get("frameType").getAsInt();
switch(frameType) {
case 4: return "Gem";
case 5: return "Currency";
}
if (obj.get("typeLine").getAsString().contains("Map")
&& obj.get("descrText").getAsString() != null
&& obj.get("descrText").getAsString().contains("Travel to this Map")) {
return "Map";
}
return "Equipment";
}
}
使用方法:
RuntimeTypeAdapterFactory<Item> itemAdapter = RuntimeTypeAdapterFactory.of(Item.class, new ItemTypePredicate())
.registerSubtype(Currency.class)
.registerSubtype(Equipment.class)
.registerSubtype(Gem.class)
.registerSubtype(Map.class);
Gson gson = new GsonBuilder()
.enableComplexMapKeySerialization()
.registerTypeAdapterFactory(itemAdapter).create();
层次结构的基类是Item。货币、装备、宝石和地图都继承自这个基类。