本文的出現是爲了解決如下需求:使用Gson對json數組進行解析,可是數組裏面元素的類型是多種的。數據以下:程序員
{"list":[{
"type":0,
"data":{
"id":1,
"color":"red"
}
},{
"type":1,
"data":{
"id":1,
"name":"case"
}
}]}
可能你會說data中的對應的實體能夠包括全部data中的字段就能夠了,那麼你採用這種方法我只能說太low了,不是不能夠這麼作,要是遇到很龐大的實體類,那麼你會發現裏面甚至須要上百個字段。咱們這裏舉例只是爲了說明方便,因此給的數據都比較簡單,重在思路。json
如何設計數組
爲了解決上面的問題,那麼我想到的是三種處理方法:服務器
方法一:也就是上文所說的那種很low的作法咯,把全部的字段都放在一個實體類中。數據結構
這種方法對應初級選手確實感受還不錯,不用思考太多就能夠解決解析問題,不過這不是咱們程序員應該知足的。(上文已經吐槽過了) ide
方法二:對於數組中data數據結構不一樣,那麼字段就不統一命名成data,而是根據實的結構服務器返回不一樣的字段,如:colorEntity,userEntity。那麼對應的實體類應該是這樣的形式:ui
public class ListEntity{ int type; User userEntity; Color colorEntity; }
缺點很明顯。①沒有統一的數據字段;②添加新類型,服務器加字段須要檢查新加字段名不能和已有的字段名重複(如何已有的類型多,那麼服務器工做就須要更細心);③Gson對應的解析實體類會由於list結構豐富而變得很龐大,由於每種類型都須要一個對應的字段。 this
固然優勢也很明顯。簡單易懂,遇到問題很容易處理,可讀性強。spa
此方法前提條件就是須要服務器配合,要是你用現成的服務器那麼這種方法徹底就不用考慮了。 設計
方法三:根據不一樣的type返回不一樣的data值(也就是如今示例中的樣子),添加Gson解析器來完成解析(可能不少童鞋對此感到很陌生,其實很簡單)。
這種方法就須要對Gson的解析有必定了解。本文也是重點解說如何設計這種解析而且給出demo,下文就是對此方法進行講解。
1、Gson對應的實體類
首先咱們知道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>(); }
二、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; } }
三、使用解析器解析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,歡迎交流。