安卓中解析json数据

一、概述

  • JSON是JavaScript Object Notation的简称,起源于js(javascript)它是一种轻量级的数据交换格式,JSON不仅在js中广泛使用,同时还在其他领域得到广泛使用,如c,c++,java,Php,swift等等,成为了一种通用的理想数据交换格式,它有两种数据结构,分别是对象,数组,它形式上有花括号{}和中括号[]嵌套,{}中的是代表对象,[]中的为数组,即对象中有数组,数组中又有对象,而且以及键/值对出现。
  • json语法:
    • 数据在键值对中
    • 数据有逗号分离
    • 花括号保存对象
  • json的值:
    • 数字(整数或浮点数)
    • 字符串(在双引号中)
    • 逻辑值(true或false)
    • 数组(在方括号中)
    • 对象(在大括号中)
    • null
  • json和xml的比较
    • 数据体积小,花费流量比xml少
    • 可读性比xml稍差,但格式化后也很可观
    • 与JavaScript交互比xml方便
    • 速度比xml快
    • 拥有与xml同样多的解析方式

大概了解了JSON,下面将介绍在Android中通过采用android内置的org.json包,android 3.0 新出的JsonReader,google提供的gson解析json这三种常用的方式解析json;这里笔者只介绍前两种解析方式。

二、准备json数据

  • 要学习怎么解析json,咋们先要得到json数据,得到json数据方式有很多种,比如:webservice接口api,自己写个服务器端,或者自己在代码中写一个json格式的字符串。下面我们将通过金山词霸开放平台为我们提供的每日一句的api接口演示三种解析json的方法。
    金山词霸每日一句api接口:http://open.iciba.com/dsapi
    要解析json,我们得先知道要解析json的格式及内容,我们先用浏览器访问每日有一句api接口看看返回的数据。
{"sid":"2436","tts":"http:\/\/news.iciba.com\/admin\/tts\/2016-12-06-day.mp3","content":"Don't make a promise when you are in Joy. Don't reply when you are Sad.Don't take decisions when you are Angry.Think Twice.Act Wise.","note":"\u5f53\u4f60\u559c\u60a6\u65f6\uff0c\u4e0d\u8981\u8f7b\u6613\u5730\u627f\u8bfa\u3002\u5f53\u4f60\u60b2\u4f24\u65f6\uff0c\u4e0d\u8981\u8f7b\u6613\u5730\u56de\u590d\u3002\u5f53\u4f60\u6124\u6012\u65f6\uff0c\u4e0d\u8981\u8f7b\u6613\u505a\u51fa\u51b3\u5b9a\u3002\u4e09\u601d\u800c\u540e\u884c\uff0c\u660e\u667a\u4e4b\u6cd5\u3002","love":"1066","translation":"\u8bcd\u9738\u5c0f\u7f16\uff1a\u8fd9\u4e09\u53e5\u8bdd\u5c0f\u7f16\u89c9\u5f97\u5728\u751f\u6d3b\u4e2d\u771f\u7684\u53d7\u76ca\u65e0\u7a77\uff0c\u7279\u522b\u662f\u7b2c\u4e00\u53e5\u548c\u7b2c\u4e09\u53e5\u3002\u4eba\u4f1a\u56e0\u4e3a\u559c\u60a6\u51b2\u660f\u5934\u8111\u8bf4\u5927\u8bdd\u6216\u8005\u662f\u778e\u8bb8\u8bfa\uff0c\u6700\u540e\u53c8\u505a\u4e0d\u5230\u3002\u8fd9\u6837\u6b21\u6570\u591a\u4e86\u5468\u56f4\u7684\u4eba\u5c31\u6ca1\u6709\u4eba\u613f\u610f\u76f8\u4fe1\u4f60\u8bf4\u7684\u8bdd\uff0c\u6574\u4e2a\u4eba\u7684\u5206\u91cf\u5728\u670b\u53cb\u4e2d\u4f1a\u8d8a\u6765\u8d8a\u4f4e\u3002\u5f53\u4f60\u6124\u6012\u7684\u65f6\u5019\u5462\uff0c\u4e5f\u5343\u4e07\u4e0d\u8981\u505a\u51fa\u4ec0\u4e48\u51b3\u5b9a\uff0c\u56e0\u4e3a\u5982\u8bba\u4f60\u505a\u51fa\u4ec0\u4e48\u51b3\u5b9a\u4e4b\u540e\u57fa\u672c\u90fd\u4f1a\u975e\u5e38\u540e\u6094\uff01\u6240\u4ee5\u5982\u679c\u5927\u5bb6\u771f\u7684\u5f88\u6c14\u6124\u4e5f\u8981\u7ed9\u81ea\u5df1\u4e00\u4e2a\u7f13\u51b2\u7684\u65f6\u95f4\uff0c\u518d\u51b3\u5b9a\u4e0b\u4e00\u6b65\u600e\u4e48\u505a~","picture":"http:\/\/cdn.iciba.com\/news\/word\/20161206.jpg","picture2":"http:\/\/cdn.iciba.com\/news\/word\/big_20161206b.jpg","caption":"\u8bcd\u9738\u6bcf\u65e5\u4e00\u53e5","dateline":"2016-12-06","s_pv":"0","sp_pv":"0","tags":[{"id":null,"name":null}],"fenxiang_img":"http:\/\/cdn.iciba.com\/web\/news\/longweibo\/imag\/2016-12-06.jpg"}

这是什么东西,看不懂是不是?没关系,这里有一个格式化json数据的工具,格式化之后的json就非常可观了,HiJson32位和64位下载

  • 使用HiJson格式化json数据
    如下图所示,格式化后的字符json数据就相当可观了。
    这里写图片描述
    这是格式化后的json数据:
{
    "caption": "词霸每日一句",
    "content": "Don't make a promise when you are in Joy. Don't reply when you are Sad.Don't take decisions when you are Angry.Think Twice.Act Wise.",
    "dateline": "2016-12-06",
    "fenxiang_img": "http://cdn.iciba.com/web/news/longweibo/imag/2016-12-06.jpg",
    "love": "1066",
    "note": "当你喜悦时,不要轻易地承诺。当你悲伤时,不要轻易地回复。当你愤怒时,不要轻易做出决定。三思而后行,明智之法。",
    "picture": "http://cdn.iciba.com/news/word/20161206.jpg",
    "picture2": "http://cdn.iciba.com/news/word/big_20161206b.jpg",
    "s_pv": "0",
    "sid": "2436",
    "sp_pv": "0",
    "tags": [
        {}
    ],
    "translation": "词霸小编:这三句话小编觉得在生活中真的受益无穷,特别是第一句和第三句。人会因为喜悦冲昏头脑说大话或者是瞎许诺,最后又做不到。这样次数多了周围的人就没有人愿意相信你说的话,整个人的分量在朋友中会越来越低。当你愤怒的时候呢,也千万不要做出什么决定,因为如论你做出什么决定之后基本都会非常后悔!所以如果大家真的很气愤也要给自己一个缓冲的时间,再决定下一步怎么做~",
    "tts": "http://news.iciba.com/admin/tts/2016-12-06-day.mp3"
}
  • 注意:由于今天金山提供的json数据tags数组中无内容,所以笔者选择往期的json数据讲解,笔者使用这份json数据举例。
{
    "caption": "词霸每日一句",
    "content": "You aspire to do great things? Begin with little ones.  ",
    "dateline": "2015-12-07",
    "fenxiang_img": "http://cdn.iciba.com/web/news/longweibo/imag/2015-12-07.jpg",
    "love": "2437",
    "note": "想成就大事,就要从小事开始。(Augustine of Hippo)",
    "picture": "http://cdn.iciba.com/news/word/2015-12-07.jpg",
    "picture2": "http://cdn.iciba.com/news/word/big_2015-12-07b.jpg",
    "s_pv": "6694",
    "sid": "1683",
    "sp_pv": "121",
    "tags": [
        {
            "id": "13",
            "name": "名人名言"
        },
        {
            "id": "16",
            "name": "治愈系"
        }
    ],
    "translation": "词霸小编:拥有好心情的最佳方式就是“干正事”。学会了规定的单词,读完了必读的书,收尾了工作,锻炼没有偷懒…那么遇到态度不好的出租司机,多收钱的看车大妈,排队加塞的无良青年也会一笑置之,心中充实,才有底气快乐。【关注词霸小妹微信(微信号:ijinshanciba),有惊喜呦!】",
    "tts": "http://news.iciba.com/admin/tts/2015-12-07-day.mp3"
}

三、解析json数据

  • 方式一:使用org.json包解析
/**
     * 通过org.json解析json
     * @param jsonStr json字符串
     * @throws JSONException  格式不对,转换异常
     */
    public static Sentence parseJsonByOrgJson(String jsonStr) throws JSONException{
        // 使用该方法解析思路,遇到大括号用JsonObject,中括号用JsonArray
        // 第一个是大括号{}
        JSONObject jsonObj = new JSONObject(jsonStr);
        // 新建Sentence对象
        Sentence sentence = new Sentence();
        // 以下是体力活
        String caption = jsonObj.getString("caption");
        String content = jsonObj.getString("content");
        String dateline = jsonObj.getString("dateline");
        String fenxiang_img = jsonObj.getString("fenxiang_img");
        String love = jsonObj.getString("love");
        String note = jsonObj.getString("note");
        String picture = jsonObj.getString("picture");
        String picture2 = jsonObj.getString("picture2");
        String s_pv = jsonObj.getString("s_pv");
        String sp_pv = jsonObj.getString("sp_pv");
        String translation = jsonObj.getString("translation");
        String tts = jsonObj.getString("tts");
        sentence.caption = caption;
        sentence.content = content;
        sentence.dateline = dateline;
        sentence.fenxiang_img = fenxiang_img;
        sentence.love = love;
        sentence.note = note;
        sentence.picture = picture;
        sentence.picture2 = picture2;
        sentence.s_pv = s_pv;
        sentence.sp_pv = sp_pv;
        sentence.translation = translation;
        sentence.tts = tts;

        // 解析关键字tags,它是一个JsonArray,遇到[]
        JSONArray jsonArray = jsonObj.getJSONArray("tags");
        // 新建Tag集合
        List<Sentence.Tag> tags = new ArrayList<Sentence.Tag>();
        for(int i=0;i<jsonArray.length();i++){
            Sentence.Tag tag = new Sentence.Tag();
            // jsonArray里的每一项都是JsonObject
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            tag.id = jsonObject.getInt("id");
            tag.name = jsonObject.getString("name");
            tags.add(tag);
        }
        sentence.tags = tags;

        return sentence;
    }
使用这种方法解析JSON,看注释,没什么好多的,总结一句话就是:遇到{}用JSONObject,遇到[]用JSONArray,这样你就可以说你精通org.json解析JSON了。
  • 方式二:使用JsonReader解析JSON,JsonReader解析JSON有点类似PULL解析XML,主要的方法还是nextName()将游标后移。
 /**
     * Call requires API level 11 (current min is 8): new
     * android.util.JsonReader 通过org.json解析json
     * 
     * @param jsonStr
     *            json字符串
     * @throws Exception
     */
    @SuppressLint("NewApi")
    public static Sentence parseJsonByJsonReader(String jsonStr)
            throws Exception {
        // 新建Sentence
        Sentence sentence = new Sentence();
        // 新建Tag集合
        List<Sentence.Tag> tags = new ArrayList<Sentence.Tag>();
        JsonReader reader = new JsonReader(new StringReader(jsonStr));
        // 遇到{,开始解析对象
        reader.beginObject();
        while (reader.hasNext()) {
            String name = reader.nextName();
            if ("caption".equals(name)) {
                sentence.caption = reader.nextString();
            }
            if ("content".equals(name)) {
                sentence.content = reader.nextString();
            }
            if ("dateline".equals(name)) {
                sentence.dateline = reader.nextString();
            }
            if ("fenxiang_img".equals(name)) {
                sentence.fenxiang_img = reader.nextString();
            }
            if ("love".equals(name)) {
                sentence.love = reader.nextString();
            }
            if ("note".equals(name)) {
                sentence.note = reader.nextString();
            }
            if ("picture".equals(name)) {
                sentence.picture = reader.nextString();
            }
            if ("picture2".equals(name)) {
                sentence.picture2 = reader.nextString();
            }
            if ("s_pv".equals(name)) {
                sentence.s_pv = reader.nextString();
            }
            if ("sid".equals(name)) {
                sentence.sid = reader.nextString();
            }
            if ("sp_pv".equals(name)) {
                sentence.sp_pv = reader.nextString();
            }
            if ("translation".equals(name)) {
                sentence.translation = reader.nextString();
            }
            if ("tts".equals(name)) {
                sentence.tts = reader.nextString();
            }
            if ("tags".equals(name)) {
                // 遇到[,开始解析数组
                reader.beginArray();
                while (reader.hasNext()) {
                    // 遇到{,开始解析对象
                    reader.beginObject();
                    Sentence.Tag tag = new Sentence.Tag();
                    if ("id".equals(reader.nextName())) {
                        tag.id = reader.nextInt();
                    }
                    if ("name".equals(reader.nextName())) {
                        tag.name = reader.nextString();
                    }
                    // 遇到},对象解析结束
                    reader.endObject();
                    tags.add(tag);
                }
                sentence.tags = tags;
                // 遇到],数组解析结束
                reader.endArray();
            }
        }
        // 遇到},对象解析结束
        reader.endObject();
        return sentence;
    }

当开始解析对象时(遇到”{“就JsonReader.beginObject()),当这个对象解析结束了(遇到”}”)就endObject()结束对象的解析。
当开始解析数组时(遇到”[“就JsonReader.beginArray()),当这个数组解析结束了(遇到”]”)就endArray()结束数组的解析。
注意nextXXX()都会是游标后移,如果有数据忘了解析等等导致游标错位,将会导致数据类型错乱,这个时候就会很容易发生:java.lang.IllegalStateException: Expected a X but was Y …参数匹配异常。所以一定不要漏了数据和注意每一次移动游标。

  • 校验json解析数据是否正确
    检验json数据的方法通常是将解析出来的内容用Log输出来,但这里节点较多,显然这方法是不可取的。可以用调试的方法检验json数据是否解析正确。具体做法为在解析json数据的第一句打一个断点,然后让程序逐行执行,如果解析出现措错误,程序会直接跳到catch异常的代码那里,这样就知道是哪一行代码出错了;出错原因通常为解析节点的键写错了。如解析无错误,则程序能一行一行往下顺序执行完毕。
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值