写在前面
关于GSON的入门级使用,这里就不提了,如有需要可以看这篇博文《Google Gson的使用方法,实现Json结构的相互转换》,写的很好,通俗易懂。
我为什么写这篇文章呢?因为前几晚跟好友 xiasuhuei321 探讨了一下GSON解析复杂的JSON的时候,能不能只解析源数据中的数组,甚至只解析数组的某一部分。探讨了二十分钟,得出结论:没用过,不知道。
所以今天特地研究了一下,发现真的So Easy!之前想复杂了,学习的过程中,发现有五种方式分别搞定不同情况的JSON数组,也就是今天说的五大招!
在介绍之前先来个约定,比如下面的这个JSON:
"muser": [ { "name": "zhangsan", "age": "10", "phone": "11111", "email": "[email protected]" }, ... ]
这里的 "muser" ,也就是数组的名称,称它为数据头,防止跟里面的 字段 有歧义;
如果没有数据头,那就叫它纯数据,或者纯数组数据;
代码中用到的 JsonArray/JsonObject 等熟悉的类全部来自 GSON 。
开始过招吧!
第一招 A
没有数据头的纯数组JSON如何解析?
根据约定,也就是这个 JSON 里面只有一个数组(JsonArray),而且这个数组没有名字,比如像下面这样的:
[ { "name": "zhangsan", "age": "10", "phone": "11111", "email": "[email protected]" }, { "name": "lisi", "age": "20", "phone": "22222", "email": "[email protected]" }, ... ]
这里其实是最简单的一种 JSON 数组格式,强大的 GSON 可以直接解析成一个 List 。但在这里我先不直接解析,就用比较老实的方法去解析,因为需要引出两个东西。
首先我们需要建立一个Bean对象,注意变量名要跟字段名称一致,没什么好说的:
public class UserBean { //变量名跟JSON数据的字段名需要一致 private String name ; private String age; private String phone; private String email; ... }
下面这是解析过程,先看代码:
/** * 解析没有数据头的纯数组 */private void parseNoHeaderJArray() { //拿到本地JSON 并转成String String strByJson = JsonToStringUtil.getStringByJson(this, R.raw.juser_1); //Json的解析类对象 JsonParser parser = new JsonParser(); //将JSON的String 转成一个JsonArray对象 JsonArray jsonArray = parser.parse(strByJson).getAsJsonArray(); Gson gson = new Gson(); ArrayList<UserBean> userBeanList = new ArrayList<>(); //加强for循环遍历JsonArray for (JsonElement user : jsonArray) { //使用GSON,直接转成Bean对象 UserBean userBean = gson.fromJson(user, UserBean.class); userBeanList.add(userBean); } mainLView.setAdapter(new UserAdapter(this, userBeanList)); }
从代码中可以看出解析的步骤如下:
无论 JSON 来自本地还是网络获取,都要先将 JSON 转成 String ;
需要一个 JSON 解析类对象将JSON的字符串转成 JsonArray ,前提是我们知道 JSON 中只有纯数组;
循环遍历 JsonArray ,并用 GSON 解析成相应的对象。
代码本身不难,容易看懂,但前面说到,这里我故意这样写,因为需要说两个东西:
1、JsonParse
从名称我们就可以看出,这是一个解析类。没错,它可以把 JSON 数据分别通过 getAsJsonObject和 getAsJsonArray 解析成 JsonObject 和 JsonArray 。这跟普通的解析 JSON 差不多,不展开说。
2、JsonElement
这个类我是第一次见,它是一个抽象类,代表 JSON 串中的某一个元素,可以是 JsonObject/JsonArray/JsonPrimitive/... 中的任何一种元素。
所以在上面的代码中,我们可以看到它能把 JsonArray 中的每一个元素转成 JsonObject ,甚至说它本身就是 JsonObject 。
好了,就为了说这两个东西。记住,后面将会用到。
来看一下运行的图吧,很简单的东西,后面的二三都是这样的效果,就不重复贴图了:
第二招 Q
有数据头的纯数组数据该怎么解析?
内容跟上面的 JSON 一模一样,只不过加了一个名称 "muser" ,也就是约定好的 数据头 :
{ "muser": [ { "name": "zhangsan", "age": "10", "phone": "11111", "email": "[email protected]" }, { "name": "lisi", "age": "20", "phone": "22222", "email": "[email protected]" }, ... ] }
有人说,这还不简单,在第一招中的 getAsJsonArray 加一个字符串就是咯,就像这样:
JsonArray jsonArray = parser.parse(strByJson).getAsJsonArray("muser");
思路是对的,但是不要忘了,数组装在一个 { } 括起来的 JsonObject 里。还记得上面的 JsonParse 么,它的 getAsJsonObject 可以做到这点,所以代码就是这样啦,很简单就不再解释了:
/** * 解析有数据头的纯数组 */private void parseHaveHeaderJArray() { //拿到本地JSON 并转成String String strByJson = JsonToStringUtil.getStringByJson(this, R.raw.juser_2); //先转JsonObject JsonObject jsonObject = new JsonParser().parse(strByJson).getAsJsonObject(); //再转JsonArray 加上数据头 JsonArray jsonArray = jsonObject.getAsJsonArray("muser"); Gson gson = new Gson(); ArrayList<UserBean> userBeanList = new ArrayList<>(); //循环遍历 for (JsonElement user : jsonArray) { //通过反射 得到UserBean.class UserBean userBean = gson.fromJson(user, new TypeToken<UserBean>() {}.getType()); userBeanList.add(userBean); } mainLView.setAdapter(new UserAdapter(this, userBeanList)); }
注意,这里又引出了一个东西:TypeToken ,它是什么呢?
3、TypeToken<T>
这个东西很有意思,本来我不知道到是干嘛的,看了看源码,看不懂。后来无意发现它所在的包:
import com.google.gson.reflect.TypeToken;
哎哟我去,reflect 这不是反射么,一下子就明白了。没错,它其实是一个匿名内部类,看一下官方解释:
GSON 提供了 TypeToken 这个类来帮助我们捕获(capture)像 List<T> 这样的泛型信息。Java编译器会把捕获到的泛型信息编译到这个匿名内部类里,然后在运行时就可以被 getType() 方法用反射的 API 提取到。
解释的很官方,实际上就是一句 通俗但不严谨 的话,它将泛型 T 转成 .class 。比如上面的 TypeToken<UserBean> 经过 getType() 后就是 UserBean.class 。
好了,说到这里基本铺垫就完成了,再次强调一下:
对于上面的 JSON 完全可以直接通过 GSON 转成 List ,不用这么麻烦,我只是为了引出3个小知识。
第三招 W
有数据头的复杂数据该如何解析呢?
简单的说完了,铺垫也铺完了,来看一看复杂的吧:
{ "code": 200, "msg": "OK", "muser": [ { "name": "zhangsan", "age": "10", "phone": "11111", "email": "[email protected]" }, { "name": "lisi", "age": "20", "phone": "22222", "email": "[email protected]" }, ... ] }
这里就不再是纯数组数据了,还有两个凑数的不知道干嘛用的字段,这里也有数据头,之前用的是笨方法,现在来真正见识一下GSON的威力吧。
第一步根据 JSON 建立 Bean ,注意这里的 Bean 是返回所有字段,因为 GSON 能直接解析成 List ,所以 Bean 是下面这样的,同样把占地方的 get/set 省略:
/** * Created by xiarui on 2016/8/30. * 返回所有结果的Bean */public class ResultBean { //注意变量名与字段名一致 private int code; private String msg; private List<UserBean> muser; public class UserBean{ private String name ; private String age; private String phone; private String email; ... } ... }
注意,这个 ResultBean 里面有一个 UserBean 。 它虽然跟上面第一第二招内容一样,但是作用不一样,这是作为 JsonArray 解析后存入 List 中的对象。
算了,有点拗口,直接上代码吧:
/** * 有消息头 复杂数据 常规方式 */private void parseComplexJArrayByCommon() { //拿到Json字符串 String strByJson = JsonToStringUtil.getStringByJson(this, R.raw.juser_3); //GSON直接解析成对象 ResultBean resultBean = new Gson().fromJson(strByJson,ResultBean.class); //对象中拿到集合 List<ResultBean.UserBean> userBeanList = resultBean.getMuser(); //展示到UI中 mainLView.setAdapter(new ResultAdapter(this, userBeanList)); }
没错,就是这么四句话搞定第一二招的内容。看出GSON的强大了吧,当然如果有人想不开只写一句话的话:
mainLView.setAdapter(new ResultAdapter(this,new Gson().fromJson(JsonToStringUtil.getStringByJson(this,R.raw.juser_3),ResultBean.class).getMuser()));
我也是没意见的,不过请对自己好一点,谢谢。
第四招 E
只想解析复杂JSON中的数组或数组中的某部分内容怎么办?
共同學習,寫下你的評論
評論加載中...
作者其他優質文章