Gson_五招之内搞定任何json数据

文章出处:http://www.cnblogs.com/jianyungsun/p/6647203.html

 

关于GSON入门级别的应用,这里就不提了;有需要的同学自行百度,成功毕竟是留给勤奋的人嘛!!!

首先,不要GSON这个东西,总结一下:好用  不难!!!  是不是瞬间嗨皮了,进入正文。。。

"muser": [
    {      
       "name": "zhangsan","age": "10","phone": "11111","email": "11111@11.com"
    },
    ...
]

这里的"muser",也就是数组的名称(顺带科普一下,在前台本人理解的数组等同于后台的集合,比如list),称它为数据头,防止跟里面的Object的字段有歧义,这个数据头也有类似key的功能,个人理解哈,有错误请指出;

如果没有这个数据头呢,那就是纯数据,或者叫他传输组数据;

提前说一下,代码中的JsonArray/JsonObject 全部来自GSON

 


第一招!!!
没有数据头的纯数组数据如何让解析呢?太简单啦。。。
    
    [
      {    
          "name": "zhangsan",    "age": "10",    "phone": "11111",    "email": "11111@11.com"
      },
      {  
           "name": "lisi",    "age": "20",    "phone": "22222",    "email": "22222@22.com"
      },
      ...
    ]
    
   从数据上可以看出,这是一个JsonArray,里面有多个Object,这其实是一种最简单的json数据,强大的GSON可以直接将其转换成List,就问牛不牛比!!!但是在这里不直接解析,需要引出两个其他的东西;
   首先建立一个Bean实体,注意变量名要和json的字段名称一致,这种操作还是留个大家去做,下面是解析过程
   private void parseNoHeaderJArray() {
          //首先拿到本地json数据,并转换成String  如何拿到看个人啦
          String strByJson = JsonToStringUtil.getStringByJson(this, R.raw.juser_1);
          //Json的解析类对象 JsonParser
          JsonParser parser = new JsonParser();
          //JSONString转换成JsonArray对象
          JsonArray jsonArray = parser.parse(strByJson).getAsJsonArray();
          
          Gson gson = new Gson();
          ArrayList<UserBean> userBeanList = new ArrayList<>();
          
          //遍历jsonArray
          for(JsonElement user:jsonArray){
              //使用Gson 直接转换成Bean对象
              UserBean userBean = gson.fromJson(user,UserBean.class);
              userBeanList.add(userBean);
          }
          //打印即可。。。  不做操作
   }
  
   从代码中可以看出解析步骤如下:

无论你的JSON从那里获取,无论是本地还是网络,都需要将JSON数据转换成String

需要一个JSON解析类将JSON字符串转换成JsonArray,前提是我们知道JSON中只有纯数组;

遍历转换的对象,使用GSON解析成相应的对象;


代码本身不难,这样写的目的是为了引出两个东西:
    1.JsonParser:从名称我们就可以看出,这是一个解析类;他可以把Json数据分别通过getAsJsonObjectgetAsJsonArray解析成JsonObjectJsonArray;
    2.JsonElemet:他是一个抽象类,代表Json串中某一个元素,可以是JsonObject/JsonArray/..中的任何一种元素。

第二招!!!
有数据头的数据要怎么解析呢?
{  
    "muser":
       [
        {    
         "name": "zhangsan",      "age": "10",      "phone": "11111",      "email": "11111@11.com"
        },
        {    
         "name": "lisi",      "age": "20",      "phone": "22222",      "email": "22222@22.com"
        },
        ...
      ]
}

直接上代码  不多说!!!
private void parseHaveHeaderJArray(){
    //首先拿到本地json数据,并转换成String
    String strByJson = JsonToStringUtil.getStringByJson(this, R.raw.juser_2);
    //先转JsonObject  因为json的最外层是一个Object
    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);
    }
    
    //打印即可。。。  不做操作
}

问题又来了!TypeToken 是什么鬼?
3.这个东西很有意思,本来我不知道到是干嘛的,看了看源码,看不懂。后来无意发现它所在的包:
import com.google.gson.reflect.TypeToken;
哎哟我去, reflect 这不是反射么,一下子就明白了。没错,它其实是一个匿名内部类,看一下官方解释:
GSON 提供了 TypeToken 这个类来帮助我们捕获(capture)像 List 这样的泛型信息。Java编译器会把捕获到的泛型信息编译到这个匿名内部类里,然后在运行时就可以被 getType() 方法用反射的 API 提取到。
解释的很官方,实际上就是一句 通俗但不严谨 的话,它将泛型 T 转成 .class 。比如上面的 TypeToken 经过 getType() 后就是 UserBean.class
好了,说到这里基本铺垫就完成了,再次强调一下:
对于上面的 JSON 完全可以直接通过 GSON 转成 List ,不用这么麻烦,我只是为了引出3个小知识。

第三招!!!
有数据头的复杂数据该如何让解析?
{  
    "code": 200,  
    "msg": "OK",  
    "muser": [
    {      
        "name": "zhangsan", "age": "10", "phone": "11111", "email":"11111@11.com"
    },
    {      
        "name": "lisi", "age": "20", "phone": "22222", "email": "22222@22.com"
    },
    ...
      ]
}

这里就不再是纯数组数据了,还有两个凑数的不知道干嘛用的字段,这里也有数据头,之前用的是笨方法,现在来真正见识一下GSON的威力吧。
第一步根据 JSON 建立 Bean ,注意这里的 Bean 是返回所有字段,因为 GSON 能直接解析成 List ,所以 Bean 是下面这样的,同样把占地方的 get/set 省略:

public class ResultBean {  
 //注意变量名与字段名一致    
 private int code;    
 private String msg;    
 private List<UserBean> muser;    
 private UserBena userBean;
    ...
}

注意,这个 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<UserBean> userBeanList = resultBean.getMuser();
    
    //后续操作。。。
}

第四招!!!
指向解析复杂JSON中的数组或者数组中的某一部分怎么办?
还是上面的JSON数据,这里为了篇幅就不贴重复代码了,假如我只想取 “muser” 这个数组中的年龄(age)大于30岁的怎么办?

OK,当然可以先全部解析,再从 List 中取。那假如我有一万条数据呢?全部解析不是很麻烦呢?
所以一个思路就是第一二招中说的: 遍历!
OK,你会问先遍历还不是要读一万条,是的,还是要读一万条,但是假如我要把这些存入数据库呢?假如一万条数据中只有一条符合条件,难道我先存一万条,再从数据库中查询么?
当然这种情况是极端情况,但也说明了一个问题,不能所有情况下都先全部解析,假如有一万个字段,Bean还得写多长可怕。

上代码!!!
private void parseComplexJArrayByDirect() {
    //拿到JSON字符串
    String strByJson = JsonToStringUtil.getStringByJson(this, R.raw.juser_3);
    List<UserBean> userBeanList = new ArrayList<>();
    
    //拿到数组
   JsonArray jsonArray = new JsonParser.parse(strByJson).getAsJsonObject().getAsJsonArray("muser");
  
   //循环遍历数组  拿到符合条件的数据
   for(JsonElement user:jsonArray){
       UserBean userBean = new Gson().fromJson(user,new TypeToken<UserBean>(){}.getType());
       //根据条件过滤
       if(Integer.parseInte(userBean.getAge()) > 30){
          userBeanList.add(userBean);
       }
   }
   //ok  搞定
}

第五招!!!
如果一个 JSON 数据很很很复杂怎么解析?

{  
"group":
{    
"user":
{    
 "name": "张三",      "age": "10",      "phone": "11111",      "email": "11111@11.com"
 },    
 "info":
 {      "address": "北京",      "work": "Android Dev",      "pay": "10K",      "motto": "先定一个小目标,比如我先赚一个亿"
 }
 }
}

三种方式解析:
第三招,全部解析出来;
第四招,要什么解析什么;
第五招,反人类的 JsonReader (只做参考,不推荐,代码量较大)

至于为什么反人类,不好说。大家看代码就知道了,代码很简单,跟 XML 的解析差不多,是根据节点来的,至于怎么用,还是那句话直接看代码吧,确实处理起来逻辑清晰,但是代码量上,真的不敢恭维。

/**
 * 通过JsonReader的方式去解析
 */
 private void parseComplexJArrayByReader() throws IOException {
    String strByJson = JsonToStringUtil.getStringByJson(this, R.raw.juser_4);
    JsonReader reader = new JsonReader(new StringReader(strByJson));    
    try {
        reader.beginObject();
        String tagName = reader.nextName();        
        if (tagName.equals("group")) {            //group这个节点
            readGroup(reader);
        }
        reader.endObject();
    } finally {
        reader.close();
    }
}

/**
 * group这个节点
 *
 * @param reader JsonReader
 *
 /private void readGroup(JsonReader reader) throws IOException {
    reader.beginObject();    
    while (reader.hasNext()) {
        String tagName = reader.nextName();        
        if (tagName.equals("user")) {
            readUser(reader);
        } else if (tagName.equals("info")) {
            readInfo(reader);
        }
    }
    reader.endObject();
}

/**
 * 读用户基本消息 user节点
 *
 * @param reader JsonReader
 */
 private void readUser(JsonReader reader) throws IOException {
    reader.beginObject();    
    while (reader.hasNext()) {
        String tag = reader.nextName();        
        if (tag.equals("name")) {
            String name = reader.nextString();
            nameText.setText(name);
        } else if (tag.equals("age")) {
            String age = reader.nextString();
            ageText.setText(age);
        }
        ...        else {
            reader.skipValue();//忽略
        }
    }
    reader.endObject();
}

/**
 * 读用户其他消息 info节点
 *
 * @param reader JsonReader
 */private void readInfo(JsonReader reader) throws IOException {
    reader.beginObject();    
    while (reader.hasNext()) {
        String tag = reader.nextName();        
        if (tag.equals("address")) {
            String address = reader.nextString();
            addressText.setText(address);
        } else if (tag.equals("work")) {
            String work = reader.nextString();
            workText.setText(work);
        }
        ...        else {
            reader.skipValue();//忽略
        }
    }
    reader.endObject();
}


好了  结束了!!!

 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cpongo11

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值