自定义gson序列化的抽象类

时间:2015-10-17 14:53:44

标签: java serialization gson

也许我的方向错误,但我有一个我想读的元素列表。

我有一个抽象基类,我们称之为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>。有什么想法吗?

1 个答案:

答案 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);
        }
    }
}