本文的出现是为了解决如下需求:使用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,欢迎交流。