簡體   English   中英

自定義gson序列化的抽象類

[英]Custom gson serialization for an abstract class

也許我正朝着錯誤的方向奔跑,但我有一份我想讀的元素清單。

我有一個抽象基類讓我們稱它為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> 有任何想法嗎?

如何將此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);
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM