Gson解析數組多類型元素


 

本文的出現是為了解決以下需求:使用Gsonjson數組進行解析,但是數組里面元素的類型是多種的。數據如下:

{"list":[{
    "type":0,
    "data":{
        "id":1,
        "color":"red"
    }
},{
    "type":1,
    "data":{
        "id":1,
        "name":"case"
    }
}]}

可能你會說data中的對應的實體可以包括所有data中的字段就可以了,那么你采用這種方法我只能說太low了,不是不可以這么做,要是遇到很龐大的實體類,那么你會發現里面甚至需要上百個字段。我們這里舉例只是為了說明方便,所以給的數據都比較簡單,重在思路。

 

如何設計

為了解決上面的問題,那么我想到的是三種處理方法:

方法一:也就是上文所說的那種很low的做法咯,把所有的字段都放在一個實體類中。

這種方法對應初級選手確實感覺還不錯,不用思考太多就可以解決解析問題,不過這不是我們程序員應該滿足的。(上文已經吐槽過了) 

方法二:對於數組中data數據結構不同,那么字段就不統一命名成data,而是根據實的結構服務器返回不同的字段,如:colorEntityuserEntity。那么對應的實體類應該是這樣的形式:

public class ListEntity{

  int type;

  User userEntity;

  Color colorEntity;

}

缺點很明顯。①沒有統一的數據字段;②添加新類型,服務器加字段需要檢查新加字段名不能和已有的字段名重復(如何已有的類型多,那么服務器工作就需要更細心);③Gson對應的解析實體類會因為list結構豐富而變得很龐大,因為每種類型都需要一個對應的字段。 

當然優點也很明顯。簡單易懂,遇到問題很容易處理,可讀性強。

此方法前提條件就是需要服務器配合,要是你用現成的服務器那么這種方法完全就不用考慮了。 

方法三:根據不同的type返回不同的data值(也就是現在示例中的樣子),添加Gson解析器來完成解析(可能很多童鞋對此感到很陌生,其實很簡單)。

這種方法就需要對Gson的解析有一定了解。本文也是重點解說如何設計這種解析並且給出demo,下文就是對此方法進行講解。

 

1Gson對應的實體類

首先我們知道ArrayList里面的元素都是相同的類型,那么如何才能使用不同的類型呢?當然就是集合里面的元素使用一個基類,然后具體的實體類都繼承這個基類。示例:

我們有3個類:

 這個類就是剛剛說的基類,所有list字段里面對應實體的基類

public class TypeSuper {

}

list字段里面對應的其中一種類型TypeA

public class TypeA extends TypeSuper {

public int id;

public String name;

 

public TypeA(int id, String name) {

super();

this.id = id;

this.name = name;

}

}

 

list字段里面對應的其中另一種類型TypeB

public class TypeB extends TypeSuper { 

  public int id;

  public String color;

 
  public TypeB(int id, String color) {

    super();

    this.id = id;

    this.color = color;

  }

}
 

 

Gson對應的實體類TypeResult

public class TypeResult {

List<TypeSuper> data = new ArrayList<TypeSuper>();

}

 

 

2、Gson反序列化

根據json字符串進行解析,示例代碼如下:

Gson解析器TypeResultDeserializer 

public class TypeResultDeserializer implements JsonDeserializer<TypeResult> {

    @Override
    public TypeResult deserialize(JsonElement arg0, Type arg1,
            JsonDeserializationContext arg2) throws JsonParseException {
        JsonObject obj = arg0.getAsJsonObject();
        JsonArray asJsonArray = obj.get("list").getAsJsonArray();
        TypeResult result = new TypeResult();
        for (JsonElement jsonElement : asJsonArray) {
            JsonObject jsonOb = jsonElement.getAsJsonObject();
            int type = jsonOb.get("type").getAsInt();
            if (type == 0) {
                JsonObject child = jsonOb.get("data").getAsJsonObject();
                int id = child.get("id").getAsInt();
                String name = child.get("color").getAsString();
                result.data.add(new TypeB(id, name));
            } else if(type == 1) {
                JsonObject child = jsonOb.get("data").getAsJsonObject();
                int id = child.get("id").getAsInt();
                String name = child.get("color").getAsString();
                result.data.add(new TypeA(id, name));
            }
        }
        return result;
    }
}

 


3、使用解析器解析Demo

public class Test {

    public static void main(String[] args) {
        GsonBuilder gsonb = new GsonBuilder();
        gsonb.registerTypeAdapter(TypeResult.class, new TypeResultDeserializer());
        gsonb.serializeNulls();
        Gson gson = gsonb.create();
        String json = "{\"list\":[{" + "\"type\":0," + "\"data\":{"
                + "\"id\":1," + "\"color\":\"red\"" + "}" + "},{"
                + "\"type\":1," + "\"data\":{" + "\"id\":1,"
                + "\"color\":\"case\"" + "}" + "}]}";
        List<TypeSuper> item = gson.fromJson(json, TypeResult.class).data;
        for (TypeSuper baseItem : item) {
            if (baseItem instanceof TypeA) {
                System.out.println(((TypeA) baseItem).name);
            } else if (baseItem instanceof TypeB) {
                System.out.println(((TypeB) baseItem).color);
            }
        }
    }
}

 

看完整個步驟,最核心的就是自定義解析器,根據自己的需求進行解析。以上就完整解說了方式三的具體操作流程。如果讀者有更好的方式解析希望可以分享一下。 

 

如果文中有任何疑問或者不妥之處歡迎留言交流。在此也留下QQ群311536202,歡迎交流。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM