Android解析JSON,你真的需要三方庫科展?

一般情況下均牢,如果服務器返回 JSON 數(shù)據(jù),而且你又是做 Android 的才睹,那么你首先想到的可能是GSON徘跪,或是fastJson這樣的框架。這些框架能夠很方便和快速的讓我們將 JSON 轉換成本地對象琅攘,是開發(fā)的首選垮庐。但是引用三方庫也是有代價的,顯而易見的就是包體積增大坞琴,庫的升級等哨查。這個時候,就需要想一想我們是不是必須要使用三方庫了剧辐。

其實在 Android 上處理 JSON 解恰,Google 已經給我們提供了一些類锋八,而這些類滿足了大多數(shù)簡單的需求。如果我們只是需要對 JSON 進行簡單的解析處理护盈,那么完全可以避免引入第三方庫挟纱。

json_icon.png

org.json

Android的參考文檔中,我們能發(fā)現(xiàn)一個包腐宋,名為:org.json紊服。這個包下主要有四個類:

類名 描述
JSONArray A dense indexed sequence of values.
JSONObject A modifiable set of name/value mappings.
JSONStringer Implements toString() and toString()
JSONTokener Parses a JSON (RFC 4627) encoded string into the corresponding object.

關于 org.json 的代碼,還可以在 https://github.com/stleary/JSON-java 上找到胸竞,而且里面的類遠不止這4個欺嗤,里面很多內容都值得去探索一下。但是由于本文僅專注于在 Android 上利用此工具處理 JSON卫枝,所以就僅僅討論著四個類煎饼,下面將分別對著四個類逐一講解。

JSONObject

這個類是這四個類中最關鍵的一個校赤,它表示了一個可更改且無序的鍵值對集合吆玖,更簡單一點,可以直接認為這個類表示了一個 JSON 的信息马篮。在 JSON 字符串中沾乘,其表示了一個包裹在花括號的字符串,鍵和值之間使用冒號隔開浑测,鍵值和鍵值之間使用逗號隔開的翅阵。

在這個類中,其鍵名是唯一且不為null的字符串迁央。而值則可以為 JSONObject掷匠、JSONArrayStrings岖圈、Booleans讹语、IntegersLongs幅狮、Double 或者 JSONObject.NULL募强。特別注意,這里的NULL可不是null崇摄,而是JSONObject的一個內部類擎值。

對于這個類,在使用時要要注意的就是在調用時逐抑,其會按照調用的方法進行類型轉換鸠儿。下面就介紹一下三類函數(shù):

  • getXXX() 獲取一個值,此方法如果發(fā)生失敗,例如沒有找到對應的鍵值或類型轉換失敗进每,就會拋出一個JSONException異常汹粤;
  • optXXX() 此類方法也是用于獲取一個值,但是如果發(fā)生失敗田晚,其不會拋出異常嘱兼,而是返回一個默認值;
  • put()此類方法就是向對象中插入一個鍵值對贤徒。特別注意其插入NULLnull是不同的芹壕;

剛說到此類中的 NULL,它與 JAVA 中的null是不一樣的接奈,它僅僅是JSONObject中用于標識null的對象踢涌。舉個例子:

  1. put(name, null) 這個方法調用將會移除該對象中對應的鍵值;
  2. put(name, JSONObject.NULL) 將會往對象中添加一個鍵值序宦,而其值為 JSONObject.NULL睁壁;

下面通過一個實際使用的代碼來演示該類:

JSONObject jsonObject = new JSONObject("{\"first_name\":\"Taylor\",\"last_name\":\"swifter\"}");
String firstName = jsonObject.getString("first_name");
String lastName = jsonObject.getString("last_name");
Log.i("swifter", firstName + " " + lastName);   //輸出 Taylor swifter

jsonObject.put("first_name", "Avril");
Log.i("swifter", jsonObject.toString());   //輸出 {"first_name":"Avril","last_name":"swifter"}

通過代碼也可以看到JSONObject的簡單用法,可以看到這個類也可以用來進行構建 JSON 字符串互捌,只要不斷向類中使用put()方法插入或是修改潘明,在最后使用toString()就可以得到最終的 JSON 了。

關于這個toString()這個函數(shù)后面還會提到疫剃,下面介紹的是在這四個類中第二重要的類:表示數(shù)組的JSONArray钉疫。

JSONArray

該類表示了 JSON 中的值的數(shù)組硼讽,可以簡單的理解其為一個普通數(shù)組巢价,也有getXXX()optXXX()方法,但是基本都需要傳入索引值固阁。這個類代表了JSON 中的一個包裹在方括號的字符串壤躲,值和值之間使用逗號隔開的信息。

除此之外备燃,這個類有很多性質都與JSONObject 一樣碉克,比如說類型轉換,對于NULLnull的處理并齐,有get漏麦,putopt方法等况褪,所以撕贞,只要你熟悉了JSONObject,那么使用這個類测垛,也會非常容易:

JSONArray jsonArray = new JSONArray("[10,11,12,13,14,15,16]");
for(int index = 0; index < jsonArray.length(); index++) {
    Log.i("swifter", index+" : "+jsonArray.getInt(index));
}

此段代碼的輸出是將10到16這幾個數(shù)組中的數(shù)打印出來捏膨。在更多情況下,該類一般都是與JSONObject一起使用的,因為普遍的 JSON 都是其中的某一個字段是數(shù)組号涯,因此需要先使用JSONObject進行解析目胡,然后使用getJSONArray()再來獲取這個數(shù)組的信息并進行處理:

JSONObject jsonObject = new JSONObject("{\"first_name\":\"Taylor\",\"last_name\":\"swifter\",
                                         \"array\":[first, second, third, fourth]}");
JSONArray jsonArray = jsonObject.getJSONArray("array");
for(int index = 0; index < jsonArray.length(); index++) {
    Log.i("swifter", index+" : "+jsonArray.getString(index));
}

此段待會會將 JSON 中array的四個值以字符串的形式依次打印出來。

JSONStringer

此類可以用于快速構建 JSON 文本链快,它實現(xiàn)了JSONObject中的兩個toString()方法誉己,對于大多數(shù)程序員來說,應該直接調用JSONObjecttoString()方法而忽略這個類的:

JSONObject object = ...
String json = object.toString();

它使用了一種類似于 XML 事件解析的方式來實現(xiàn) JSON 構建域蜗,例如它有key()方法用于插入鍵巫延,有value()方法用于插入值,而且還有array()endArray()用于開始和結束插入數(shù)組地消,有object()endObject()方法用于開始和結束插入 JSON 內容炉峰。

僅僅說其有什么方法比較澀會難懂,那就上代碼:

JSONStringer jsonStringer = new JSONStringer();
jsonStringer.object().key("first_name").value("Taylor").key("last_name").value("swifter");
jsonStringer.key("array").array().value(12).value(13).value(14).endArray().endObject();
Log.i("swifter", jsonStringer.toString());      //輸出 {"first_name":"Taylor","last_name":"swifter","array":[12,13,14]}

可以看到對于 JSON 的構建脉执,該類就是通過這幾個方法的調用來實現(xiàn)的疼阔。

剛才說到JSONObject類的toString()方法就是通過這個類來實現(xiàn)的,那它是怎么實現(xiàn)的呢半夷?現(xiàn)在就來看看代碼吧婆廊。它有兩個方法,為了簡單起見巫橄,我們就看其中一個:

/**
 * Encodes this object as a compact JSON string, such as:
 * <pre>{"query":"Pizza","locations":[94043,90210]}</pre>
 */
@Override public String toString() {
    try {
        JSONStringer stringer = new JSONStringer();
        writeTo(stringer);
        return stringer.toString();
    } catch (JSONException e) {
        return null;
    }
}

void writeTo(JSONStringer stringer) throws JSONException {
    stringer.object();
    for (Map.Entry<String, Object> entry : nameValuePairs.entrySet()) {
        stringer.key(entry.getKey()).value(entry.getValue());
    }
    stringer.endObject();
}

這段代碼顯示了JSONObject是如何處理toString()的淘邻,其主要的工作在writeTo()這個函數(shù)中,而又可以看到湘换,這個函數(shù)也是調用的JSONStringerkey()value()等方法來實現(xiàn) JSON 構造的宾舅。另一個toString()也類似,僅僅是是用了JSONStringer的另一個構造函數(shù)而已彩倚。

JSONTokener

這個類是四個類中最不常用的一個類筹我,它能夠將一個 JSON 字符串(RFC 4627)解析到相關的對象,對于大多數(shù)客戶端僅僅需要使用它的構造函數(shù)和nextValue()函數(shù):

 String json = "{"
         + "  \"query\": \"Pizza\", "
         + "  \"locations\": [ 94043, 90210 ] "
         + "}";
 JSONObject object = (JSONObject) new JSONTokener(json).nextValue();
 String query = object.getString("query");
 JSONArray locations = object.getJSONArray("locations");

可見帆离,這個類就是和JSONObject的構造函數(shù)一起使用的蔬蕊,用于解析 JSON 源字符串,還例如:

 JSONObject jsonobj = new JSONObject(new JSONTokener(new FileReader(new File("json.txt")))); 

上面的四個類的內容都如此吧哥谷。相比于其他第三方庫岸夯,內置的JSON解析功能上確實非常簡單,但在很多場景下也是完全夠用的们妥。當熟悉了這幾個類之后猜扮,我們也就可以權衡一下是否真的需要引用第三方庫才能完成需求了。如果能滿足的話王悍,為什么還需要引用其他庫呢破镰。

2b013df0-5b70-4c07-833e-6d95101e2d10.jpg
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子鲜漩,更是在濱河造成了極大的恐慌源譬,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件孕似,死亡現(xiàn)場離奇詭異踩娘,居然都是意外死亡,警方通過查閱死者的電腦和手機喉祭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進店門养渴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人泛烙,你說我怎么就攤上這事理卑。” “怎么了蔽氨?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵藐唠,是天一觀的道長。 經常有香客問我鹉究,道長宇立,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任自赔,我火速辦了婚禮妈嘹,結果婚禮上,老公的妹妹穿的比我還像新娘绍妨。我一直安慰自己润脸,他們只是感情好,可當我...
    茶點故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布痘绎。 她就那樣靜靜地躺著津函,像睡著了一般肖粮。 火紅的嫁衣襯著肌膚如雪孤页。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天涩馆,我揣著相機與錄音行施,去河邊找鬼。 笑死魂那,一個胖子當著我的面吹牛蛾号,可吹牛的內容都是我干的。 我是一名探鬼主播涯雅,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼鲜结,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起精刷,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤拗胜,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后怒允,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體埂软,經...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年纫事,在試婚紗的時候發(fā)現(xiàn)自己被綠了勘畔。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,626評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡丽惶,死狀恐怖炫七,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情钾唬,我是刑警寧澤诉字,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站知纷,受9級特大地震影響壤圃,放射性物質發(fā)生泄漏。R本人自食惡果不足惜琅轧,卻給世界環(huán)境...
    茶點故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一伍绳、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧乍桂,春花似錦冲杀、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至憋沿,卻和暖如春旺芽,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背辐啄。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工采章, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人壶辜。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓悯舟,卻偏偏與公主長得像,于是被迫代替她去往敵國和親砸民。 傳聞我的和親對象是個殘疾皇子抵怎,可洞房花燭夜當晚...
    茶點故事閱讀 43,494評論 2 348

推薦閱讀更多精彩內容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理奋救,服務發(fā)現(xiàn),斷路器反惕,智...
    卡卡羅2017閱讀 134,629評論 18 139
  • 1 反射機制&JSON解析 【 Java的高級特性:反射機制 publicclass Student { pu...
    征程_Journey閱讀 887評論 0 0
  • 馬斯克是誰隘梨?這個時代的人如果不認識他,大咖君覺得那你也是厲害了舷嗡,網上到處都是他的消息轴猎,你是如何完美避過他的新聞呢?...
    大咖仁品閱讀 313評論 0 1
  • 一整天了进萄,情緒的低落捻脖,不想看見他,這兩天他所做的一切都感動不到我中鼠,甚至于不想他這般可婶,覺得他是出于愧疚,跟他說話也只...
    俠骨丹心9號閱讀 170評論 0 0
  • 這是我人生中最任性的一次援雇,任由自己流離浪蕩在上海這一座既熟悉又陌生的城市矛渴。感覺熟悉因為我愛的人在這里,感覺陌生因為...
    四月瘋子閱讀 572評論 1 1