一般碰到json解析大家都会想到要使用解析工具来帮助我们更高效快捷的来解析json,常用的工具用法推荐一篇博客,方便移步观看
http://blog.csdn.net/frankcheng5143/article/details/50042015
使用工具固然效率很高,但是要求json数据格式固定,如果碰到格式不固定的,首先写javabean的时候就会遇到问题,更别说解析的时候了,最后导致解析常常出错。如果这个时候想到不用解析工具,直接用jsonobject解析,解析效率慢不说,碰到格式复杂点的,很容易就把自己绕晕了。实际应用当中,大部分json数据都是固定格式的,少部分不固定的也必然有规律可寻。
下面分享x下当json数据有部分格式不固定的时候的解析方法。
1.当格式不固定的内容不重要时,直接忽略掉
这里就要用到gson的注解了,使用@Expose可以区分实体中不想被序列化的属性,使用方法见下面的链接
2,当格式不固定的内容很重要且有规律可寻时,自定义这部分的解析方式
我们先分析一下下图的json格式
director和star下都有“1”,“m_1”,”2”,“m_2”这样类似的字段,而且数据开头的下面都是name和link这两个字段,m开头的下面都是只有link这一个字段。再想一个director和star这种字段,就可以断定star下面不一定每次都是1-4和m_1-m_4,这个时候如果拿到的json数据格式出一个1-5,必然解析就会出错,这种时候针对“1”,“m_1”自定义解析方式,不仅可以简单化javabean还可以避免出错。
下面来解析:
首先,把1和m_1放到一个ItemList对象中
public class ItemList {
List<Item> itemList = new ArrayList<>();
public List<Item> getItemList() {
return itemList;
}
}
定义Item
public class Item {
@Expose
@SerializedName("name")
public String name;
@Expose
@SerializedName("link")
public String link;
public String m_link;
}
对应director和stat的javaBean写法就变成
public class Director {
@SerializedName("showname")
@Expose
private String showname;
@SerializedName("data")
@Expose
private ItemList workgroup;
/**
* @return The showname
*/
public String getShowname() {
return showname;
}
/**
* @param showname The showname
*/
public void setShowname(String showname) {
this.showname = showname;
}
/**
* @return The workgroup
*/
public ItemList getWorkgroup() {
return workgroup;
}
/**
* @param workgroup The workgroup
*/
public void setWorkgroup(ItemList workgroup) {
this.workgroup = workgroup;
}
}
public class Star {
@SerializedName("showname")
@Expose
private String showname;
@SerializedName("data")
@Expose
private ItemList data;
/**
* @return The showname
*/
public String getShowname() {
return showname;
}
/**
* @param showname The showname
*/
public void setShowname(String showname) {
this.showname = showname;
}
/**
* @return The data
*/
public ItemList getData() {
return data;
}
/**
* @param data The data
*/
public void setData(ItemList data) {
this.data = data;
}
}
然后就是重写deserialize方法
Gson gson = new GsonBuilder().setPrettyPrinting().registerTypeAdapter(ItemList.class, new JsonDeserializer<ItemList>() {
@Override
public ItemList deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
//只自定义解析Itemlist这一部分内容
JsonObject jo = json.getAsJsonObject();
int maxId = -1;
for (Map.Entry<String, JsonElement> entry : jo.entrySet()) {
String s = entry.getKey();
try {
int i = Integer.parseInt(s);
if (i > maxId)
maxId = i;//先拿到最大值
} catch (Exception e) {
}
}
ItemList list = new ItemList();
for (int i = 1; i <= maxId; i++) {
Item item = new Item();
//根据jo中是数字开头还是m开头给item中的对象赋值
JsonObject value = jo.getAsJsonObject(Integer.toString(i));
if (value != null) {
item.name = value.get("name").getAsString();
item.link = value.get("link").getAsString();
list.getItemList().add(item);
}
JsonObject mLink = jo.getAsJsonObject("m_" + i);
if (mLink != null && mLink.get("link") != null) {
try {
item.m_link = mLink.get("link").getAsString();
} catch (Exception e) {
e.printStackTrace();
}
}
}
return list;
}
}).create();
定义好解析方式之后就是使用了
MovieResp<Movie> resp = gson.fromJson(text, new TypeToken<MovieResp<Movie>>() {}.getType());
System.out.println(resp.getResult().getData().get(0).getData().get(0).getDirector().getWorkgroup().getItemList().get(0).link);