Python中Json庫(kù)loads方法ValueError異常分析

之前用python(2.7版本)開發(fā)公司網(wǎng)絡(luò)協(xié)議的解析工具,直接從網(wǎng)絡(luò)抓包pcap文件中解析出協(xié)議交換流程.

公司協(xié)議中二進(jìn)制和Json兩種格式類型共存.針對(duì)二進(jìn)制內(nèi)容,python的struct這庫(kù)用起來還是蠻順手的.針對(duì)Json協(xié)議部分,首選就是本文的Json庫(kù).對(duì)于Json庫(kù)的詳細(xì)介紹,可以網(wǎng)上搜一把,資料還是很全的.(

這里討論的是json庫(kù)的loads方法.由于struct庫(kù)獲取過來的數(shù)據(jù),都是以pythonh中的字符串類型的保存的,所以我采用json的loads方法(load是從文件中加載).于是乎, 問題就出現(xiàn)了, 我使用時(shí)loads拋出了一個(gè)ValueError異常.查看下程序堆棧信息,可以發(fā)現(xiàn)loads方法的調(diào)用流程是:
loads()->_default_decoder.decode(s)
其中decode的庫(kù)源代碼如下

def decode(self, s, _w=WHITESPACE.match):  
       """Return the Python representation of ``s`` (a ``str`` or ``unicode`` 
       instance containing a JSON document) 
       """  
       obj, end = self.raw_decode(s, idx=_w(s, 0).end())  
       end = _w(s, end).end()  
       if end != len(s):  
           raise ValueError(errmsg("Extra data", s, end, len(s)))  
       return obj  

其中WHITESPACE是一個(gè)正則表示式對(duì)象,其定義代碼如下:

WHITESPACE = re.compile(r'[ \t\n\r]*', FLAGS)  

就是匹配空白字符的一個(gè)正則表達(dá)式對(duì)象,所以
idx=_w(s, 0).end()
就是把字符串前面的空白字符都跳過了soga.

PS:正則表示式對(duì)象的match方法的第二個(gè)入?yún)?,代表匹配的起始位?br> 然后self.raw_decode完成了字符串內(nèi)容的解析(相關(guān)代碼可以自己研究哦),返回了一個(gè)obj對(duì)象(這貨就是我們需要的)和一個(gè)end( json格式中‘}’的位置+1,end返回一個(gè)開區(qū)間的結(jié)束位置) ,end現(xiàn)在代表json處理了的字符串的長(zhǎng)度

end = _w(s, end).end()  

_w這老兄又把end加上了json字符串后面空白字符串的長(zhǎng)度(如果有的話).
主題來了:

if end != len(s):  
            raise ValueError(errmsg("Extra data", s, end, len(s)))  

如果json處理的字符串長(zhǎng)度和我們給的長(zhǎng)度不一致,那就game over,拋出一個(gè)ValueError異常了.什么情況下會(huì)導(dǎo)致長(zhǎng)度不統(tǒng)一呢,根據(jù)json庫(kù)的算法,只要你在后面的空白字符再跟上其他非空白字符,那就能得到夢(mèng)寐以求的ValueError.
由于我要解析的json字符串,后面都會(huì)帶上c字符結(jié)尾符0,所以這就是真相.
我的解決方法是,對(duì)到手的json字符串先預(yù)處理下:

strJson = "".join([ string.strip().rsplit("}" , 1)[0] ,  "}"] )   

主要就是用rsplit函數(shù)切掉最右邊“}”后面的字符串.
PS:我是感覺end!=len(s)這個(gè)判斷不是很好,不過stackoverflow上面一些家伙的解釋,是json庫(kù)不支持解釋"{}{}"這種類型的json字符串,從這方法考慮,倒也說的通.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 今天需要解析一個(gè)非常長(zhǎng)的json字符串,中間碰到了各種問題,總結(jié)了一下所有的注意事項(xiàng)。首先我有一個(gè)字符串,原本非常...
    leyu閱讀 5,289評(píng)論 0 0
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,545評(píng)論 19 139
  • 基礎(chǔ)1.r''表示''內(nèi)部的字符串默認(rèn)不轉(zhuǎn)義2.'''...'''表示多行內(nèi)容3. 布爾值:True、False(...
    neo已經(jīng)被使用閱讀 1,879評(píng)論 0 5
  • 今天在車上看到一群人在一個(gè)地方舉著旗子抗議,我很好奇就問司機(jī)師傅,師傅告訴我一些外來人員給子女爭(zhēng)取在北京接受義務(wù)教...
    國(guó)璽同學(xué)閱讀 406評(píng)論 0 0
  • 我們少年刻苦學(xué)習(xí),考進(jìn)理想的大學(xué)學(xué)習(xí),走入社會(huì)奮斗在工作崗位,和愛的人一起組建家庭,一個(gè)人的一生就是在不斷的追求和...
    作者清涼閱讀 916評(píng)論 0 0

友情鏈接更多精彩內(nèi)容