4.4.2 JSONObject 和 GSON 解析 JSON 数据详解

本节例程下载地址:WillFLowJSON

一、JSON简介

我们之前已经掌握了 XML 格式数据的解析方式,那么接下来我们要去学习一下如何解析 JSON 格式的数据,在学习之前,我们先将这两者做一个简单的比较。

XML与JSON的对比:
  • JSON和XML的数据可读性基本相同
  • JSON和XML同样拥有丰富的解析手段
  • JSON相对于XML来讲,数据的体积小
  • JSON与JavaScript的交互更加方便
  • JSON对数据的描述性比XML较差
  • JSON的速度要远远快于XML

总之,比起 XML, JSON 的主要优势在于它的体积更小,在网络上传输的时候可以更省流量。但缺点在于,它的语义性较差,看起来不如 XML 直观。

(1)JSON 的格式规范

就像协议一样,JSON 也是有一套规范的,毕竟服务端和客户端双方一般来讲都是通过 JSON 字符串来传递数据的。

它的语法规则如下:

  • 数据在“名称/值”对中;
  • 数据由逗号分隔;
  • 花括号保存对象;
  • 方括号保存数组;
(2)JSON数据的书写格式范例
[
    { "id":"1","name":"WGH","age":"18" },
    { "id":"2","name":"WillFlow","age":"16"  }
]
(3)JSON校验工具

我们除了解析JSON还可以自己拼接JSON,当然如果你自己拼了一个JSON字符串又不知道对不对, 可以用校验工具进行校验,比如:点击这里,然后把自己拼接的JSON字符串贴上去,就可以校验正确与否了。

(4)Android给我们提供的JSON解析类

这些JSON解析类的API都存在于org.json包下,而我们用到的类有下面这些:

  • JSONObject: JSON对象,可以完成Json字符串与Java对象的相互转换
  • JSONArray: JSON数组,可以完成Json字符串与Java集合或对象的相互转换
  • JSONStringer: JSON文本构建类,这个类可以帮助快速和便捷的创建JSON text, 每个JSONStringer实体只能对应创建一个JSON text
  • JSONTokener:JSON解析类
  • JSONException:JSON异常

二、用 JSONObject 解析 JSON 格式数据

首先在MainActivity中定义一个JSON 字符串常量,代码如下:
    private static final String JSON = "[\n" +
            "  {\"id\":\"1\",\"version\":\"1.5\",\"name\":\"Apple\"},\n" +
            "  {\"id\":\"2\",\"version\":\"1.6\",\"name\":\"WillFlow\"},\n" +
            "  {\"id\":\"3\",\"version\":\"1.7\",\"name\":\"WGH\"}\n" +
            "]";

这样我们就把 JSON 格式的数据准备好了,下面就开始在 Android 程序中解析这些数据。

修改 MainActivity 中的代码,如下所示:
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        parseJSONWithJSONObject(JSON);
    }

    private void parseJSONWithJSONObject(String jsonData) {
        try {
            JSONArray jsonArray = new JSONArray(jsonData);
            for (int i = 0; i < jsonArray.length(); i++) {
                JSONObject jsonObject = jsonArray.getJSONObject(i);
                String id = jsonObject.getString("id");
                String name = jsonObject.getString("name");
                String version = jsonObject.getString("version");
                Log.i(TAG, "id : " + id);
                Log.i(TAG, "name : " + name);
                Log.i(TAG, "version : " + version);
                Log.i(TAG, "————————————————————");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

可以看到,解析 JSON 的代码真的是非常简单,由于我们定义的是一个 JSON 数组,因此这里首先是将数据传入到了一个 JSONArray 对象中,然后循环遍历这个 JSONArray,从中取出的每一个元素都是一个 JSONObject 对象,每个 JSONObject 对象中又会包含 id、 name 和 version 这些数据。接下来只需要调用 getString() 方法将这些数据取出,并打印出来即可。

编译运行查看日志数出

三、用 GSON 解析 JSON 格式数据

如何你认为使用 JSONObject 来解析 JSON 数据已经非常简单了,那你就太容易满足了。谷歌提供的 GSON 开源库可以让解析 JSON 数据的工作简单到让你不敢想象的地步,那我们肯定是不能错过这个学习机会的。

首先,在Gradle中配置如下依赖:
dependencies {
    ......
    compile 'com.google.code.gson:gson:2.8.1'
}

这时候GSON框架就加载好了,我们需要手动同步一下。

如果你的 Android Studio 中没有安装GSON插件的话,可以这样安装:

完成之后重启 Android Studio 即可。

那么 GSON 库究竟是神奇在哪里呢?其实它主要就是可以将一段 JSON格式的字符串自动映射成一个对象,从而不需要我们再手动去编写代码进行解析了,比如说一段 JSON 格式的数据如下所示:

{"name":"Tom","age":20}

那我们就可以定义一个 Person 类,并加入 name 和 age 这两个字段,然后只需简单地调用如下代码就可以将 JSON 数据自动解析成一个 Person 对象了:

Gson gson = new Gson();
Person person = gson.fromJson(jsonData, Person.class);

如果需要解析的是一段 JSON 数组会稍微麻烦一点,我们需要借助 TypeToken 将期望解析成的数据类型传入到 fromJson() 方法中,如下所示:

List<Person> people = gson.fromJson(jsonData, new TypeToken<List<Person>>(){}.getType());

基本的用法就是这样,下面就让我们来真正地尝试一下。

这里我们首先准备好需要解析的JSON原始数据:
[
  {"id":"1","version":"1.5","name":"Apple"},
  {"id":"2","version":"1.6","name":"WillFlow"},
  {"id":"3","version":"1.7","name":"WGH"}
]
然后新建一个AppBean类,用于数据规范的定义:
/**
 * Created by   : WGH.
 */
public class AppBean {

}
然后在该类的任意位置“Alt + Insert”,然后选择“Gson Format”或者使用快捷键“Alt + S”
然后会出现这样的界面,然后把我们刚才的JSON原始数据粘贴进去后点击OK:
继续点击OK,你会发现此时的AppBean变成了这个样子:
/**
 * Created by   : WGH.
 */
public class AppBean {

    /**
     * id : 1
     * version : 1.5
     * name : Apple
     */
    private String id;
    private String version;
    private String name;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getVersion() {
        return version;
    }

    public void setVersion(String version) {
        this.version = version;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

这是一个包含了id、 name 和 version 这三个字段的数据类,并且成员变量和JSON原始数据的Key值完全相同(这点尤为重要,这是采用GSON解析的必须)。

最后在 MainAcitivyt 中定义这样的方法:
    private void parseByGSON(String jsonData) {
        Gson gson = new Gson();
        List<AppBean> appList = gson.fromJson(jsonData, new TypeToken<List<AppBean>>() {}.getType());
        for (AppBean app : appList) {
            Log.i(TAG, "id : " + app.getId());
            Log.i(TAG, "name : " + app.getName());
            Log.i(TAG, "version : " + app.getVersion());
            Log.i(TAG, "————————————————————");
        }
    }

然后调用输出即可。

编译运行查看Log输出

这样我们就就把 XML 和 JSON 这两种数据格式最常用的几种解析方法都学习完了,在网络数据的解析方面,我们已经成功毕业了。

点此进入:GitHub开源项目“爱阅”

感谢优秀的你跋山涉水看到了这里,欢迎关注下让我们永远在一起!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,383评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,522评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,852评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,621评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,741评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,929评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,076评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,803评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,265评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,582评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,716评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,395评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,039评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,027评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,488评论 2 361
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,612评论 2 350

推荐阅读更多精彩内容