Json解析框架之Gson详解

作者: 吾乃韩小呆 | 来源:发表于2017-12-21 17:17 被阅读24次

    好东西,大家享

    原文来自:http://www.iamxiarui.com/2016/08/30/android

    原文作者:iamxiarui

    1、简单的JSON数据进行解析

    [
      {
        "name": "zhangsan",
        "age": "10",
        "phone": "11111",
        "email": "11111@11.com"
      },
      {
        "name": "lisi",
        "age": "20",
        "phone": "22222",
        "email": "22222@22.com"
      },
      ...
    ]
    

    这个是最简单的一种Json数组格式,Gson可以直接将其解析成一个List。
    首先,我们需要建立一个Bean对象,注意变量名要与字段名称名称保持一致。

    推荐使用Android Studio 的GsonFormat工具

    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数据转换成String类型数据;
    ②、当JSON内只有纯属组,用JSON解析类对象将JSON字符串转为JsonArray;
    ③、遍历Json数组,使用Gson进行解析。

    a、JsonParse:解析类,它可以将Json数据分别通过getAsJsonObject 和 getAsJsonArray 解析成 JsonObject 和JsonArray 。

    b、JsonElement:一个抽象类,代表Json字符串内某个元素例如:JsonObject/JsonArray/JsonPrimitive/...

    2、有数据头的纯数组数据

    Json字符串如下,仅仅在最最简单的基础上加了一个约定好的名称为:"muser" 的数据头

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

    使用上面提到的 JsonParse 进行相关操作

    /**
     * 解析有数据头的纯数组
     */
    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));
    }
    

    c、TypeToken:为匿名反射类

    以下为官方说明:

    GSON 提供了 TypeToken 这个类来帮助我们捕获(capture)像 List 这样的泛型信息。Java编译器会把捕获到的泛型信息编译到这个匿名内部类里,然后在运行时就可以被 getType() 方法用反射的 API 提取到。

    官方要表达的话是:

    将泛型 T 转成 .class 。比如上面的 TypeToken 经过 getType() 后就是UserBean.class 。

    对于上面的 JSON 完全可以直接通过 GSON 转成 List ,不用这么麻烦,我只是为了引出3个小知识。

    3、有数据头的复杂数据

    Json的字符串如下:

    {
      "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"
        },
        ...
      ]
    }
    

    仔细观察这个字符串结构发现上面多了两个字段
    "code": 200
    "msg": "OK"
    首先创建Bean类,这里再次强调使用Android Studio 的GsonFormat工具

    此处省略set/get方法

    /**
     * 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));
    }
    

    4、只解析复杂JSON中的数组或数组中的某部分内容

    Json字符串和上面的一样:

    {
      "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"
        },
        ...
      ]
    }
    

    对于这个问题,不需要一一进行解析,但是有一点需要做的是,需要遍历。

    完整代码解析代码如下:

    /**
     * 有数据头 复杂数据 截取方式
     */
    private void parseComplexJArrayByDirect() {
        //拿到JSON字符串
        String strByJson = JsonToStringUtil.getStringByJson(this, R.raw.juser_3);
        List<UserBean> userBeanList = new ArrayList<>();
    
        //拿到数组
        JsonObject jsonObject = new JsonParser().parse(strByJson).getAsJsonObject();
        JsonArray jsonArray = jsonObject.getAsJsonArray("muser");
    
        //循环遍历数组
        for (JsonElement user : jsonArray) {
            UserBean userBean = new Gson().fromJson(user, new TypeToken<UserBean>() {
            }.getType());
            //根据条件过滤
            if (Integer.parseInt(userBean.getAge()) > 30) {
                userBeanList.add(userBean);
            }
        }
        mainLView.setAdapter(new UserAdapter(this, userBeanList));
    }
    

    5、若Json数据非常非常复杂如下

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

    具体解析方式如下(不要问我为啥?我看来的!!!):

    /**
     * 通过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();
    }
    

    相关文章

      网友评论

        本文标题:Json解析框架之Gson详解

        本文链接:https://www.haomeiwen.com/subject/tvyawxtx.html