数组类型不同解析问题探究
我们在开发过程中可以遇到json 数组中的具体的javaBean 不一致现象。例如:
{"list":[{
"type":a,
"data":A,
},{
"type":a,
"data":B
}]}
如上图所示,list中data的类型根据type的值而变化。像这种bean类型不一致问题,一直烦恼着开发者,现在简单介绍下,几种 可行的解决思路。
方法一:合并Bean
如果A与B中的字段不复杂,可以将A,B合并组合成一个比较大的Bean实例,他包括A和B中所有的字段。
例如:
{"list":[{
"type":"person",
"data":{
name:"小王",
age:15,
gender:"male"
},
},{
"type":"dog",
"data":{
name:"旺财",
age:2,
species:"家狗"
},
}]}
合并之后的bean 为:
public class combineBean {
public String name;
public int age;
public String gender;
public String species;
}
方法二:data字段根据type而更改
对于数组中data数据结构不同,那么字段就不统一命名成data,而是根据type的不同类型,服务器返回不同的字段,如:person,dog。那么对应的实体类应该是这样的形式:
public class ListBean{
public String type;
public PersonBean person;
public DogBean dog;
}
此方法前提条件就是需要服务器配合,要是你用现成的服务器那么这种方法完全就不用考虑了。
另外这种方法data中类型种类比较多,还会导致ListBean类比较大。而且json中字段不统一。
方法三:Json解析
既然我们的data中的实体类,根据type类型进行改变,我们可以首先解析出来type字段对应的值,然后根据type值得类型,设置data不同的类型的实体类,然后再解析data中数据。
当然关于ListBean中类型统一,可以设置data类型的接口,或者父类,然后子类实现它:
list中data字段对应的基类,
public class DataBean{}
当然你可以将data中子类中相同的字段提取出来,放在DataBean中。
有了DataBean这个虚拟的基类后,我们就可以统一ListBean的类型。
ListBean
public class ListBean{
public String type;
public DataBean data;
}
然后让data中具体的不同子类去继承父类DataBean,实现我们需要的子类。
public class PersonBean extend DataBean{
public String name;
public int age;
public String gender;
}
public class DogBean extend DataBean{
public String name;
public int age;
public String species ;
}
我们可以安装Json的解析的方法,首先将返回的json字符串慢慢解析成实体类,首先解析list,然后里面的type 我们根据type的类型然后解析data中不同类型的数据。
这个json解析唯一的难点就是必须首先要解析出type的数据,然后根据type才能确定data的不同的实体类型。
其实Gson中可以自定义解析器;
public class ListBeanDeserializer implements JsonDeserializer<TypeResult> {
@Override
public ListBean deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
if (!json.isJsonObject()) {
return null;
}
JsonObject obj = json.getAsJsonObject();
JsonArray asJsonArray = obj.get("list").getAsJsonArray();
ListBean list = new ListBean();
for (JsonElement jsonElement : asJsonArray) {
JsonObject jsonOb = jsonElement.getAsJsonObject();
String type = jsonOb.get("type").getAsString();
if (TextUtils.equal(type,"person")) {
JsonObject child = jsonOb.get("data").getAsJsonObject();
String name = child.get("name").getAsString();
int age = child.get("age").getAsInt();
String gender = child.get("gender").getAsString();
list.data=new Person(name, age,gender);
} else if(TextUtils.equal(type,"dog")) {
JsonObject child = jsonOb.get("data").getAsJsonObject();
String name = child.get("name").getAsString();
int age = child.get("age").getAsInt();
String species = child.get("species").getAsString();
list.data=new Person(name, age,species);
}
}
return list;
}
}
使用解析器解析:
protected ArrayList<ListBean> deserializerResponse(@NonNull Response response) throws IOException {
String json = null;
if (response != null && response.body() != null) {
json = response.body().string();
}
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(ListBean.class, new ListBeanDeserializer());
Gson gson = gsonBuilder.create();
return gson.fromJson(TextUtils.isEmpty(json) ? json : json.trim(), new TypeToken<ArrayList<ListBean>>() {
}.getType());
}