最近空闲时间在一款仿某条的app,一开始,采用的是api store中的数据源,但是这样,好多功能因为不能得到接口支持不能实现,因此只能。。。。。。通过fiddler抓 某条 的接口了。。
在抓一个接口的时候,发现接口的json格式并不是常规的json格式,如下:
{
//字段太多,省略非关键部分代码
"digg_count": 6,
"ordered_info": [{
"data": [{
"link": "链接。。。",
"word": "海南大学"
},
{
"link": "链接。。。",
"word": "海南航空"
}
],
"name": "labels"
},
{
"data": {
"like_num": 1312,
"user_like": 0
},
"name": "like_and_rewards"
},
{
"ad_data": "xxxx",
"name": "ad"
},
{
"data": [{
"aggr_type": 1,
"group_id": 6519344328546976260,
"impr_id": "260",
"item_id": 6519344328546976260,
"log_pb": {
"impr_id": "201802241624280100100"
},
"open_page_url": "url",
"title": "阿司匹林肠溶片是终身吃,还是吃一段时间就不吃了?",
"type_name": ""
},
{
"aggr_type": 1,
"group_id": 6523892928937460231,
"impr_id": "31",
"item_id": 6523892928937460231,
"log_pb": {
"impr_id": "20180224162428010010023222209F57"},
"open_page_url": "url",
"title": "中国战机不如土耳其?巴铁为何弃中国战机而选择土耳其战机",
"type_name": ""
}
],
"name": "related_news"
}
]
}
可以发现,ordered_info是一个数组,常规的数组,里面的bean应该是一样的字段,但是ordered_info中需要四个bean,有一种比较笨的方法,是写一个实体类,把所有的字段全部包含进去,但是如果遇到数据字段特别庞大的时候,那就呵呵哒了。
仔细观察ordered_info下的四种类型的数据,会发现他们有一个共同的字段,那就是 name
,那就好办了,可以通过name
这个字段让程序知道应该用哪个bean去解析。
首先建立六个bean类:BaseOrderedInfoBean、OrderedInfoBean1、OrderedInfoBean2、OrderedInfoBean3、OrderedInfoBean4、AuthorInfoBean。其中OrderedInfoBeanX是ordered_info数组下的四种类型对应的bean,BaseOrderedInfoBean是其余四个bean类的子类,AuthorInfoBean是最外层json对应的bean。
public class BaseOrderedInfoBean {
//空类
}
public class OrderedInfoBean1 extends BaseOrderedInfoBean {
private String name;
private List data;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List getData() {
return data;
}
public void setData(List data) {
this.data = data;
}
public static class DataBean {
private String link;
private String word;
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
public String getWord() {
return word;
}
public void setWord(String word) {
this.word = word;
}
}
public class OrderedInfoBean2 extends BaseOrderedInfoBean {
//具体省略。。
}
public class OrderedInfoBean3 extends BaseOrderedInfoBean {
//具体省略。。
}
public class OrderedInfoBean4 extends BaseOrderedInfoBean {
//具体省略。。
}
注意:AuthorInfoBean 中的数组中必须为BaseOrderedInfoBean
类型,实体类字段名应该通过@SerializedName("")来规范成java标准命名格式。
public class AuthorInfoBean{
@SerializedName("digg_count")
private int diggCount;
@SerializedName("ordered_info")
private List orderedInfos;
public int getDiggCount() {
return diggCount;
}
public void setDiggCount(int diggCount) {
this.diggCount = diggCount;
}
public List getOrderedInfos() {
return orderedInfos;
}
public void setOrderedInfos(List orderedInfos) {
this.orderedInfos= orderedInfos;
}
}
下面开始最关键的反序列化,需要一个类来实现JsonDeserializer
接口,在里面处理不同的类型数据即可。
public class OrderedInfoDeserializer implements JsonDeserializer {
private static final String LABELS = "labels";
private static final String LIKE_END_REWARDS = "like_and_rewards";
private static final String AD = "ad";
private static final String RELATED_NEWS = "related_news";
@Override
public BaseOrderedInfoBean deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonObject jsonObject = json.getAsJsonObject();
//获取里面的name字段,用作区分的标志
String name = jsonObject.get("name").getAsString();
switch (name) {
case LABELS:
return new Gson().fromJson(json, OrderedInfoBean1.class);
case LIKE_END_REWARDS:
return new Gson().fromJson(json, OrderedInfoBean2.class);
case AD:
return new Gson().fromJson(json, OrderedInfoBean3.class);
case RELATED_NEWS:
return new Gson().fromJson(json, OrderedInfoBean4.class);
default:
return null;
}
}
}
最后一步,把整个解析器注册到Gson实例中去:
Gson gson = new GsonBuilder()
.registerTypeAdapter(BaseOrderedInfoBean.class, new OrderedInfoDeserializer())
.create();
由于网络请求采用的是Retrofit,因此需要需要设置一下:
new Retrofit.Builder()addConverterFactory(GsonConverterFactory.create(gson)).create();
这样就能愉快的进行解析了O(∩_∩)O