Gson解析數組多類型元素

 

本文的出現是爲了解決如下需求:使用Gsonjson數組進行解析,可是數組裏面元素的類型是多種的。數據以下:程序員

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

可能你會說data中的對應的實體能夠包括全部data中的字段就能夠了,那麼你採用這種方法我只能說太low了,不是不能夠這麼作,要是遇到很龐大的實體類,那麼你會發現裏面甚至須要上百個字段。咱們這裏舉例只是爲了說明方便,因此給的數據都比較簡單,重在思路。json

 

如何設計數組

爲了解決上面的問題,那麼我想到的是三種處理方法:服務器

方法一:也就是上文所說的那種很low的作法咯,把全部的字段都放在一個實體類中。數據結構

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

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

public class ListEntity{

  int type;

  User userEntity;

  Color colorEntity;

}

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

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

此方法前提條件就是須要服務器配合,要是你用現成的服務器那麼這種方法徹底就不用考慮了。 設計

方法三:根據不一樣的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>();

}

 

 

二、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,歡迎交流。

相關文章
相關標籤/搜索