安卓中解析json数据
Posted 钟小林
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了安卓中解析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异常的代码那里,这样就知道是哪一行代码出错了;出错原因通常为解析节点的键写错了。如解析无错误,则程序能一行一行往下顺序执行完毕。
以上是关于安卓中解析json数据的主要内容,如果未能解决你的问题,请参考以下文章