項目地址:
https://github.com/liaozhoubei/HttpAndParse
JSON是一種類似 XML的語言蝴悉,是用了存儲和交換文本信息的語法。它的全稱為JavaScript Object Notation(JavaScript 對象表示法)秘症。與xml對比,它更小、更快荔燎,更易解析贸诚。
想要更好的解析JSON方庭,必須能看懂JSON數(shù)據(jù),這樣就必須了解JSON語法酱固,好在它的語法非常簡單械念,規(guī)則如下:
JSON 語法是 JavaScript 對象表示法語法的子集。
- 數(shù)據(jù)在名稱/值對中:如 "firstName" : "John"
- 數(shù)據(jù)由逗號分隔
- 花括號保存對象
- 方括號保存數(shù)組
而組成JSON的值可以為以下幾種:
- 數(shù)字(整數(shù)或浮點數(shù))
- 字符串(在雙引號中)
- 邏輯值(true 或 false)
- 數(shù)組(在方括號中)
- 對象(在花括號中)
- null
簡單的回顧了一下JSON之后运悲,我們就開始正式展開JSON解析之旅了龄减。
傳統(tǒng)的JSON解析
最傳統(tǒng)的JSON解析莫過于直接使用java中的方法,它通過原生的JSONObject和JSONArray來解析json數(shù)據(jù)班眯,下面我們就來解析這段json數(shù)據(jù)吧希停!json數(shù)據(jù)如下:
{
"personData": [
{
"age": 12,
"name": "nate",
"schoolInfo": [
{
"School_name": "清華"
},
{
"School_name": "北大"
}
],
"url": "http://pic.yesky.com/uploadImages/2014/345/36/E8C039MU0180.jpg"
},
{
"age": 24,
"name": "jack",
···
}
],
"result": 1
}
分析這段json數(shù)據(jù),
- 第一層是一個花括號括號署隘,即jsonObect對象宠能,然后這個對象里面有一個personData的JSONArray數(shù)組,以及一個result屬性
- 第二層personData的JSONArray數(shù)組磁餐,它里面除了屬性之外违崇,還有一個schoolInfo的JSONArray數(shù)組
- 第三次是schoolInfo的JSONArray數(shù)組里面的JSONObject對象
這時我們已經(jīng)將這段數(shù)據(jù)分析好了,接下來就是寫解析方法解析了诊霹。
創(chuàng)建一個Httpjson繼承Thread的線程類羞延,它能夠打開URL網(wǎng)址,然后獲取網(wǎng)絡(luò)中的JSON數(shù)據(jù)畅哑,在進行JSON解析肴楷,代碼如下:
public class Httpjson extends Thread {
private String url;
private Context context;
private ListView listView;
private JsonAdapter adapter;
private Handler handler;
public Httpjson(String url, ListView listView, JsonAdapter adapter, Handler handler) {
super();
this.url = url;
this.listView = listView;
this.adapter = adapter;
this.handler = handler;
}
@Override
public void run() {
URL httpUrl;
try {
httpUrl = new URL(url);
···
}
/**
* 從網(wǎng)絡(luò)中獲取JSON字符串,然后解析
* @param json
* @return
*/
private List<Person> jsonParse(String json) {
try {
List<Person> personlist = new ArrayList<Person>();
JSONObject jsonObject = new JSONObject(json);
int result = jsonObject.getInt("result");
if (result == 1) {
JSONArray jsonArray = jsonObject.getJSONArray("personData");
for (int i = 0; i < jsonArray.length(); i++) {
Person person = new Person();
JSONObject personData = jsonArray.getJSONObject(i);
int age = personData.getInt("age");
String url = personData.getString("url");
String name = personData.getString("name");
···
JSONArray schoolInfoArray = personData.getJSONArray("schoolInfo");
for (int j = 0; j < schoolInfoArray.length(); j++) {
JSONObject schoolInfojson = schoolInfoArray.getJSONObject(j);
String schoolName = schoolInfojson.getString("School_name");
···
}
···
}
return personlist;
} else {
Toast.makeText(context, "erro", Toast.LENGTH_SHORT).show();
}
} catch (JSONException e) {
e.printStackTrace();
Log.e("JsonParseActivity", "json解析出現(xiàn)了問題");
}
return null;
}
}
其中JsonAdapter和Person對象請看項目代碼荠呐。
這里將json數(shù)據(jù)解析出來赛蔫,然后放入List<Person>集合中供外部使用。
我們按照之前分析來研究這段json解析方法泥张。
首先是一個大括號呵恢,我們直接從傳過來的json字符串創(chuàng)建出來的jsonObject就行了,然后就可以通過它獲取result參數(shù)媚创,代碼如下:
JSONObject jsonObject = new JSONObject(json);
int result = jsonObject.getInt("result");
然后就是解析personData這個json數(shù)組渗钉,我們直接通過數(shù)組名稱獲取,代碼如下:
JSONArray jsonArray = jsonObject.getJSONArray("personData");
再接著就是解析這個數(shù)組,解析數(shù)組都是用循環(huán)解析的鳄橘,然后這個數(shù)組里面先是一個花括號声离,這又是一個jsonObject對象,代碼如下:
JSONArray jsonArray = jsonObject.getJSONArray("personData");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject personData = jsonArray.getJSONObject(i);
int age = personData.getInt("age");
String url = personData.getString("url");
String name = personData.getString("name");
···
}
在personData這個JSONObject對象中瘫怜,又有一個schoolInfo的JSONArray數(shù)組术徊,我們繼續(xù)按照上述方法獲得JSONArray,然后通過for循環(huán)獲得里面的JSONObject鲸湃,這時已達到最底層赠涮,我們就可以直接獲取School_name屬性的值了,代碼如下:
for (int j = 0; j < schoolInfoArray.length(); j++) {
JSONObject schoolInfojson = schoolInfoArray.getJSONObject(j);
String schoolName = schoolInfojson.getString("School_name");
···
}
這樣暗挑,一個完整的JSON數(shù)據(jù)就解析好了笋除!
當然,這只是解析一個簡單的JSON數(shù)據(jù)的方法炸裆,但是遇到復(fù)雜的json數(shù)據(jù)也可以如此解析垃它,首先是分析JSON數(shù)據(jù),然后就是正式解析json晒衩。
課后習(xí)題:在項目中的res-raw文件夾下嗤瞎,有newjson.txt的json數(shù)據(jù),大家可以使用這個來聯(lián)系一下json解析听系。當然啦,這個json數(shù)據(jù)的傳統(tǒng)解析方式也在項目里面寫好了虹菲,如果不懂也可以參考一下靠胜!
GSON解析
Gson 是 Google 提供的用來在 Java 對象和 JSON 數(shù)據(jù)之間進行映射的 Java 類庫”显矗可以將一個 JSON 字符串轉(zhuǎn)成一個 Java 對象浪漠,或者反過來。
這是關(guān)于GSON的介紹霎褐,相對于傳統(tǒng)的json解析址愿,使用GSON能夠極大的簡化了解析流程。
那么該如何使用GSON解析json數(shù)據(jù)呢冻璃?在這里分為以下幾步:
1响谓、在eclipse環(huán)境下,將gson的jar包復(fù)制到libs中省艳,因為這是Google提供的java類庫娘纷,是不存在java自帶的類庫中的。
2跋炕、獲取json數(shù)據(jù)赖晶,并且分析。
3辐烂、寫出json數(shù)據(jù)對應(yīng)的bean類
4遏插、使用gson解析
好了捂贿,那我們真是開始解析吧!第一步相信大家都會胳嘲,只需要在網(wǎng)上找到一個gson的jar包就可以了眷蜓,所以我們從第二步開始。
從網(wǎng)絡(luò)中獲取json數(shù)據(jù)以及從其他地方獲取數(shù)據(jù)跟普通的獲取數(shù)據(jù)沒什么區(qū)別胎围,只需要使用IO流進行操作就可以了吁系,我們這里著重的研究如何分析json數(shù)據(jù),以及寫出json數(shù)據(jù)對應(yīng)的bean類白魂!
我們在這里獲取的是res-raw目錄下的mogujson.txt數(shù)據(jù)汽纤,數(shù)據(jù)如下:
{
"date": "2014-04-23",
···
"name": "蘑菇街",
"packageName": "com.mogujie",
"safe": [
{
"safeDes": "已通過安智市場官方認證,是正版軟件",
···
},
{
"safeDes": "已通過安智市場安全檢測福荸,請放心使用",
···
},
{
"safeDes": "無任何形式的廣告",
···
}
],
"screen": [
"app/com.mogujie/screen0.jpg",
···
],
"size": 6746678,
···
}
由于行文的關(guān)系蕴坪,省略很比較多的數(shù)據(jù)信息,但是大概的信息已經(jīng)給出敬锐。
首先最外層毫無疑問是一個JSONObject對象背传,然后里面的date、name可通過JSOnObject直接取出台夺。
第二層對象是safe和screen這兩個數(shù)組径玖,然后screen數(shù)組里面直接就是一個個的字符串數(shù)據(jù),也是可以直接取出的颤介。而safe數(shù)組這要通過for循環(huán)梳星,獲得里面的JSONObject對象,然后在通過JSONObject對象獲取safeDes等數(shù)據(jù)滚朵。
那么現(xiàn)在就開始寫對應(yīng)的bean類了冤灾,如果要寫出能讓gson使用的bean類,其中的key也就是名字辕近,如date韵吨、safe這些必須一一對應(yīng)起來。其次就是在bean類中移宅,遇到花括號就寫一個class類归粉,遇到方括號就寫一個Arraylist數(shù)組。這些就是主要規(guī)則了吞杭!
所以最外層的花括號就是一個class類盏浇,所以我們創(chuàng)建一個GsonParseMoGuBean類,然后其中又有date芽狗、name這些key绢掰,所以我們直接寫出它們對應(yīng)的類型和名稱,代碼如下:
public class GsonParseMoGuBean {
public String data;
···
public String name;
···
}
這是最外層的花括號,以及它里面的值滴劲,使用GSON解析的時候攻晒,它會直接根據(jù)json數(shù)據(jù)中對應(yīng)的key,也就是data班挖、name這些名字鲁捏,從json找到對應(yīng)的key,然后賦值萧芙,如果你key名字錯誤给梅,那么就不能獲得相應(yīng)的數(shù)據(jù)。
然后輪到screen和safe這兩個數(shù)組了双揪,screen相對簡單动羽,它里面就是字符串類型的數(shù)據(jù),所以我們直接添加String類型的ArrayList就可以了渔期,如下:
public ArrayList<String> screen;
而safe數(shù)組就相對復(fù)雜它里面是一個個的花括號运吓,也就是一個個的JSONObject對象,在JSONObject對象里面才是數(shù)據(jù)疯趟,那么該如何解析呢拘哨?
safe數(shù)組中的JSONObject對象是沒有自己的key名字的,而遇到JSONObject對象也就是花括號信峻,就必須是一個class對象倦青,所以我們將這些JSONObject對象對應(yīng)的class類命名為SafeInfo,而SafeInfo則是放置在safe數(shù)組里面的站欺,所以bean類代碼如下:
public ArrayList<SafeInfo> safe;
public class SafeInfo {
public String safeDes;
···
}
}
好的姨夹,這個與GSON對應(yīng)的bean類已經(jīng)寫好了,那么我們就將詳細的bean類代碼放出來吧:
public class GsonParseMoGuBean {
public String data;
public String name;
public String packageName;
···
public ArrayList<SafeInfo> safe;
public class SafeInfo {
public String safeDes;
···
}
public ArrayList<String> screen;
}
值得一說的是這個bean類在被GSON使用的時候矾策,GSON會直接將解析到的數(shù)據(jù)存到內(nèi)存中,然后我們可以直接通過GsonParseMoGuBean獲取峭沦。而且作為一個bean類贾虽,我們不用GSON,而是用JSON的傳統(tǒng)解析方法吼鱼,這個bean類也是可以用的蓬豁。
寫好對應(yīng)的bean類,我們就直接使用GSON來解析吧~
我們在GsonParseActivity這個Activity類中使用菇肃,在點擊bt_mogujson的時候就會開始解析地粪,然后在通過TiextVew控件顯示在屏幕上,用來校驗是否解析正確琐谤,代碼如下:
switch (v.getId()) {
case R.id.bt_mogujson:
// 獲取mogujson中的數(shù)據(jù)
InputStream inputStream = getResources().openRawResource(R.raw.mogujson);
String jsonData = StreamUtils.getDecodeString(inputStream, "utf-8");
// 使用Gson解析
Gson gson = new Gson();
GsonParseMoGuBean mogujie = gson.fromJson(jsonData, GsonParseMoGuBean.class);
ArrayList<SafeInfo> safe = mogujie.safe;
for (SafeInfo info : safe) {
System.out.println(info);
}
····
// 顯示部分數(shù)據(jù)蟆技,檢驗是否解析成功
tv_gson.setText(safe.toString());
break;
···
}
我們說看到使用GSON解析就兩行代碼,如下:
Gson gson = new Gson();
GsonParseMoGuBean mogujie = gson.fromJson(jsonData, GsonParseMoGuBean.class);
創(chuàng)建一個GSON對象后,直接用fromJson方法將json數(shù)據(jù)质礼,已經(jīng)json數(shù)據(jù)對應(yīng)的bean類傳入就可以了旺聚!
所以說使用gson解析極大的簡化了解析json的流程!一切只需要兩步眶蕉,寫對應(yīng)的bean類砰粹,然后使用gson解析就完成了!
關(guān)于GSON解析就說到這里造挽,這里也給出一個課后練習(xí)給大家碱璃。
課后練習(xí):在res-raw目錄下,有newjson.txt的json數(shù)據(jù)給大家解析饭入,當然嵌器,這也給出了參考答案,在GsonParseActivity中圣拄。還有一個bilibili.txt的json數(shù)據(jù)則沒有答案嘴秸,需要大家自己解析!
json解析還是相對簡單的庇谆,只需要多練習(xí)就能夠掌握了~~