Python中Json库loads方法ValueError异常分析

之前用python(2.7版本)开发公司网络协议的解析工具,直接从网络抓包pcap文件中解析出协议交换流程.

公司协议中二进制和Json两种格式类型共存.针对二进制内容,python的struct这库用起来还是蛮顺手的.针对Json协议部分,首选就是本文的Json库.对于Json库的详细介绍,可以网上搜一把,资料还是很全的.(

这里讨论的是json库的loads方法.由于struct库获取过来的数据,都是以pythonh中的字符串类型的保存的,所以我采用json的loads方法(load是从文件中加载).于是乎, 问题就出现了, 我使用时loads抛出了一个ValueError异常.查看下程序堆栈信息,可以发现loads方法的调用流程是:
loads()->_default_decoder.decode(s)
其中decode的库源代码如下

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是一个正则表示式对象,其定义代码如下:

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

就是匹配空白字符的一个正则表达式对象,所以
idx=_w(s, 0).end()
就是把字符串前面的空白字符都跳过了soga.

PS:正则表示式对象的match方法的第二个入参,代表匹配的起始位置
然后self.raw_decode完成了字符串内容的解析(相关代码可以自己研究哦),返回了一个obj对象(这货就是我们需要的)和一个end( json格式中‘}’的位置+1,end返回一个开区间的结束位置) ,end现在代表json处理了的字符串的长度

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

_w这老兄又把end加上了json字符串后面空白字符串的长度(如果有的话).
主题来了:

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

如果json处理的字符串长度和我们给的长度不一致,那就game over,抛出一个ValueError异常了.什么情况下会导致长度不统一呢,根据json库的算法,只要你在后面的空白字符再跟上其他非空白字符,那就能得到梦寐以求的ValueError.
由于我要解析的json字符串,后面都会带上c字符结尾符0,所以这就是真相.
我的解决方法是,对到手的json字符串先预处理下:

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

主要就是用rsplit函数切掉最右边“}”后面的字符串.
PS:我是感觉end!=len(s)这个判断不是很好,不过stackoverflow上面一些家伙的解释,是json库不支持解释"{}{}"这种类型的json字符串,从这方法考虑,倒也说的通.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 今天需要解析一个非常长的json字符串,中间碰到了各种问题,总结了一下所有的注意事项。首先我有一个字符串,原本非常...
    leyu阅读 5,249评论 0 0
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,997评论 19 139
  • 基础1.r''表示''内部的字符串默认不转义2.'''...'''表示多行内容3. 布尔值:True、False(...
    neo已经被使用阅读 1,732评论 0 5
  • 今天在车上看到一群人在一个地方举着旗子抗议,我很好奇就问司机师傅,师傅告诉我一些外来人员给子女争取在北京接受义务教...
    国玺同学阅读 389评论 0 0
  • 我们少年刻苦学习,考进理想的大学学习,走入社会奋斗在工作岗位,和爱的人一起组建家庭,一个人的一生就是在不断的追求和...
    作者清凉阅读 799评论 0 0