也许我的方向错误,但我有一个我想读的元素列表。
我有一个抽象基类,我们称之为Person
:
public abstract class Person {
public int id;
public String name;
}
现在我有两种可能的实现方式:
public class Hunter implements Person {
public int skill;
// and some more stuff
}
public class Zombie implements Person {
public int uglyness;
// and some more stuff
}
现在我有了这个例子JSON:
[
{"id":1, "type":"zombie", "name":"Ugly Tom", "uglyness":42},
{"id":2, "type":"hunter", "name":"Shoot in leg Joe", "skill":0}
]
如何将此JSON读作List<Person>
?
我和TypeAdapterFactory
玩了一段时间,并试图使用一个名为CustomizedTypeAdapterFactory
的类,因为我的真实结构比上面有趣的例子稍微复杂一点。
我结束了,我想用这个调用委托序列化:
return gson.getDelegateAdapter(this, resultType);
但是我不知道如何在运行时创建此调用所需的TypeToken<T>
。有什么想法吗?
答案 0 :(得分:3)
如何将此JSON读作List?
一种可能性是创建一个像工厂一样的自定义反序列化器。
第一步是定义这个反序列化器
class PersonJsonDeserializer implements JsonDeserializer<Person> {
@Override
public Person deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
String type = json.getAsJsonObject().get("type").getAsString();
switch(type) {
case "zombie":
return context.deserialize(json, Zombie.class);
case "hunter":
return context.deserialize(json, Hunter.class);
default:
throw new IllegalArgumentException("Neither zombie or hunter");
}
}
}
它获取与键“type”关联的值,并选择正确的类型来反序列化您当前正在阅读的对象。
然后,您需要在解析器中插入此反序列化器。
public class GsonTest {
public static void main(String[] args) {
String json = "[\n" +
" {\"id\":1, \"type\":\"zombie\", \"name\":\"Ugly Tom\", \"uglyness\":42},\n" +
" {\"id\":2, \"type\":\"hunter\", \"name\":\"Shoot in leg Joe\", \"skill\":0}\n" +
"]";
Gson gson = new GsonBuilder().registerTypeAdapter(Person.class, new PersonJsonDeserializer()).create();
Type type = new TypeToken<List<Person>>(){}.getType();
List<Person> list = gson.fromJson(json, type);
for(Person p : list) {
System.out.println(p);
}
}
}
用你的例子运行它,我得到:
Zombie{id=1; name=Ugly Tom; uglyness=42}
Hunter{id=2; name=Shoot in leg Joe; skill=0}
如果类型的值已经与类名对应,您可能还想使用Class.forName
:
class PersonJsonDeserializer implements JsonDeserializer<Person> {
@Override
public Person deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
String className = json.getAsJsonObject().get("type").getAsString();
className = Character.toUpperCase(className.charAt(0)) + className.substring(1);
try {
return context.deserialize(json, Class.forName(className));
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}