Android中Json字符串解析總結(jié)

最近的項目里面對解析Json出現(xiàn)了一些問題奈梳,主要集中在iOS和Android兩者在同一個字符串識別的時候出現(xiàn)的結(jié)果不同

先看一個Json例子

{
  "aa": 1,
  "bb": "bb",
  "cc": true
}

這是一個簡單的Json字符串萄窜,包含了數(shù)字,字符串和bool值懂拾,而引起這篇文章的動機就是cc的bool值,在標準Json中對bool值的定義是 true或者false铐达,也就是說只有標準的小寫并且不帶引號的這兩個字符串才是正確的bool值岖赋。
類似于True和False這樣不標準的bool值在標準Json中是錯誤的,但是強大的抓包工具能夠讓我們對發(fā)送的請求和response的數(shù)據(jù)進行更改瓮孙,也就是說在中途如果我們將標準的true改成True唐断,那么會發(fā)生什么呢?接下來請看下面分解杭抠。
為了和上面的Json數(shù)據(jù)對應脸甘,我們創(chuàng)建一個對象

data class JsonData(var aa: Int, var bb: String, var cc: Boolean)

Google的Gson庫進行解析

    val jsonStr = "{\"aa\": 1,\"bb\": \"bb\",\"cc\": true}"

    @Test
    fun testParseJsonByGson(){
        val jsonObj = Gson().fromJson(jsonStr, JsonData::class.java)
        assertEquals(jsonObj.cc, true)
    }

上面的代碼直接將字符串轉(zhuǎn)換成了對象,沒有問題偏灿,下面我們用同樣的方法將Json字符串里面的true改成大寫的True試試

    val jsonStr = "{\"aa\": 1,\"bb\": \"bb\",\"cc\": True}"

    @Test
    fun testParseJsonByGson(){
        val jsonObj = Gson().fromJson(jsonStr, JsonData::class.java)
        assertEquals(jsonObj.cc, true)
    }

這樣測試也沒問題丹诀,這就表示Gson庫是大小寫不敏感的,好了翁垂,現(xiàn)在我們來看看Gson關于這部分的源碼就自知道了铆遭,找到 com.google.gson.stream.JsonReader 類,里面的peekKeyword方法沿猜,如下

    if (c == 't' || c == 'T') {
      keyword = "true";
      keywordUpper = "TRUE";
      peeking = PEEKED_TRUE;
    } else if (c == 'f' || c == 'F') {
      keyword = "false";
      keywordUpper = "FALSE";
      peeking = PEEKED_FALSE;
    } else if (c == 'n' || c == 'N') {
      keyword = "null";
      keywordUpper = "NULL";
      peeking = PEEKED_NULL;
    } else {
      return PEEKED_NONE;
    }

可以看出Gson里面是部分大小寫的疚脐,不管是T開頭還是t開頭的true都會認為是bool類型。
而如果我們將JsonData類中的cc改成String類型的呢邢疙?

data class JsonData(var aa: Int, var bb: String, var cc: String)

這時你會發(fā)現(xiàn)Gson會將bool中的True轉(zhuǎn)換成true棍弄,然后再把小寫的true轉(zhuǎn)換成字符串的 true 。而如果此時是Tru這樣一個錯誤的值疟游,那么就不會被轉(zhuǎn)換成小寫的true然后再轉(zhuǎn)換成字符串呼畸,而是直接轉(zhuǎn)換成字符串 "Tru"這樣大寫的。

阿里的FastJson進行解析

這里不重復說明颁虐,在正確的書寫情況下蛮原,F(xiàn)astJson和Gson是一樣的解析結(jié)果,而如果是下面這種情況另绩,將 True進行大寫

val jsonStr = "{\"aa\": 1,\"bb\": \"bb\",\"cc\": True}"

再使用FastJson進行解析

    @Test
    fun testParseJsonByFastJson(){
        val jsonObj = JSON.parseObject(jsonStr, JsonData::class.java)
        assertEquals(jsonObj.cc, true)
    }

結(jié)果是拋出異常

om.alibaba.fastjson.JSONException: default constructor not found.

我們?nèi)astJson的源碼看看為什么會這樣儒陨,找到 com.alibaba.fastjson.parser.DefaultJSONParser中的parseObject方法

if (lexer.text.startsWith("true", lexer.bp)) {
                        lexer.bp += 3;
                        lexer.next();
                        object.put(key, Boolean.TRUE);
                    }
                } else if (ch == 'f') {
                    if (lexer.text.startsWith("false", lexer.bp)) {
                        lexer.bp += 4;
                        lexer.next();
                        object.put(key, Boolean.FALSE);
                    }

這段代碼對true和false進行了限制花嘶,只有當這個值符合小寫的true和false時才被認為是bool值,如果不是蹦漠,我們這里不關心椭员,只要明白如果不是小寫的字母那么就不被認可為bool值了。

總結(jié)

這次的問題出在之前對Gson解析的不完全了解笛园,而Gson庫對出現(xiàn)的Json對象數(shù)據(jù)進行了最大程度的包容處理隘击,這里不能說誰對錯,關鍵看項目怎么用了研铆,如果要求嚴格一點埋同,那么就換成FastJson這樣的三方庫來保證,如果要求更松那么Gson就能滿足你的要求了

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末棵红,一起剝皮案震驚了整個濱河市凶赁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌逆甜,老刑警劉巖虱肄,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異忆绰,居然都是意外死亡,警方通過查閱死者的電腦和手機可岂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進店門错敢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人缕粹,你說我怎么就攤上這事稚茅。” “怎么了平斩?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵亚享,是天一觀的道長。 經(jīng)常有香客問我绘面,道長欺税,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任揭璃,我火速辦了婚禮晚凿,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘瘦馍。我一直安慰自己歼秽,他們只是感情好,可當我...
    茶點故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布情组。 她就那樣靜靜地躺著燥筷,像睡著了一般箩祥。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上肆氓,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天袍祖,我揣著相機與錄音,去河邊找鬼做院。 笑死盲泛,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的键耕。 我是一名探鬼主播寺滚,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼屈雄!你這毒婦竟也來了村视?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤酒奶,失蹤者是張志新(化名)和其女友劉穎蚁孔,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體惋嚎,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡杠氢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了另伍。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鼻百。...
    茶點故事閱讀 40,102評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖摆尝,靈堂內(nèi)的尸體忽然破棺而出温艇,到底是詐尸還是另有隱情,我是刑警寧澤堕汞,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布勺爱,位于F島的核電站,受9級特大地震影響讯检,放射性物質(zhì)發(fā)生泄漏琐鲁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一人灼、第九天 我趴在偏房一處隱蔽的房頂上張望绣否。 院中可真熱鬧,春花似錦挡毅、人聲如沸蒜撮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽段磨。三九已至取逾,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間苹支,已是汗流浹背砾隅。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留债蜜,地道東北人晴埂。 一個月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像寻定,于是被迫代替她去往敵國和親儒洛。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,044評論 2 355

推薦閱讀更多精彩內(nèi)容

  • JSON的特點: 1狼速、JSON比XML的數(shù)據(jù)傳遞的有效性高琅锻;2、JSON完全獨立于編程語言向胡;3恼蓬、JSON的本質(zhì)是具...
    程序員之路閱讀 3,505評論 0 3
  • 一.認識字符串 什么是字符串(str)字符串是python中一種常用的有序但是不可變的容器類的數(shù)據(jù)類型,可以同時存...
    2ez4ddf閱讀 478評論 0 0
  • 前言 最先接觸編程的知識是在大學里面,大學里面學了一些基礎的知識拇派,c語言荷辕,java語言,單片機的匯編語言等攀痊;大學畢...
    oceanfive閱讀 3,087評論 0 7
  • 小記: 追太陽的人的故事應是2013年中 荊棘鳥的故事應是2014年中 樹先生的故事應是2015年中 遠行客的故事...
    還樹先生閱讀 193評論 0 0
  • 海寧萬城雅園樓盤信息苟径,新動態(tài)。海寧萬城雅園樓盤信息:海寧萬城雅園地處洛塘河畔躬审,三面環(huán)水棘街,距離杭海地鐵斜橋鎮(zhèn)站僅80...
    caiao2375閱讀 263評論 0 0