无返回时处理 JSON 解码错误

Posted

技术标签:

【中文标题】无返回时处理 JSON 解码错误【英文标题】:Handle JSON Decode Error when nothing returned 【发布时间】:2012-01-12 22:48:12 【问题描述】:

我正在解析 json 数据。我没有解析问题,我正在使用simplejson 模块。但是一些 api 请求返回空值。这是我的例子:


"all" : 
    "count" : 0,
    "questions" : [     ]
    

这是我解析 json 对象的代码段:

 qByUser = byUsrUrlObj.read()
 qUserData = json.loads(qByUser).decode('utf-8')
 questionSubjs = qUserData["all"]["questions"]

正如我提到的一些请求,我收到以下错误:

Traceback (most recent call last):
  File "YahooQueryData.py", line 164, in <module>
    qUserData = json.loads(qByUser)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/simplejson/__init__.py", line 385, in loads
    return _default_decoder.decode(s)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/simplejson/decoder.py", line 402, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/simplejson/decoder.py", line 420, in raw_decode
    raise JSONDecodeError("No JSON object could be decoded", s, idx)
simplejson.decoder.JSONDecodeError: No JSON object could be decoded: line 1 column 0 (char 0)

处理此错误的最佳方法是什么?

【问题讨论】:

其实,你的问题是什么? 你回答了问题;)看起来我在真正输入问题之前提交了问题。感谢您的回答。 好的,我很高兴能帮上忙——现在看起来像是心灵感应;)不过,感谢您提出问题。祝你好运! 【参考方案1】:

Python 编程中有一条规则叫做“请求宽恕比请求许可更容易”(简称:EAFP)。这意味着您应该捕获异常而不是检查值的有效性。

因此,请尝试以下操作:

try:
    qByUser = byUsrUrlObj.read()
    qUserData = json.loads(qByUser).decode('utf-8')
    questionSubjs = qUserData["all"]["questions"]
except ValueError:  # includes simplejson.decoder.JSONDecodeError
    print('Decoding JSON has failed')

编辑:由于simplejson.decoder.JSONDecodeError 实际上继承自ValueError (proof here),我只使用ValueError 简化了catch 语句。

【讨论】:

您应该始终捕获正确的异常。否则,如果存在实际的 ValueError 异常或其他一些也继承自 ValueError 的异常,您可能会遗漏代码中的错误。 @JulieinAustin:问题是在这种情况下你真的没有太多选择——stdlib 的 json 模块会抛出 ValueError。 那么我会远离那个解码器。最初的问题是关于simplejson 模块,它确实会在输入错误时引发JSONDecodeError。查看您之前的链接。 @JulieinAustin:我会这样做,因为它实际上是......标准库。如果您不关心速度太多,我会使用现有的。是的,simplejson 以更细粒度的方式执行此操作,但它有其自身的问题。如果try...except 块只封装json.loads 调用,你会怎么说?我认为这样会更好,但需要一些锅炉位置来满足要求(例如,将异常的类更改为更细粒度的东西,但不要试图在这里拯救世界)。 ValueError 过于宽泛,无法在此上下文中使用。我相信在用户代码方面qUserData["all"]["questions"] 也可以抛出ValueError。更不用说ValueErrorsimplejson 内的其他地方提出了。当事情“无缘无故”开始破裂时,这种事情可能会在 6 个月后让你非常痛苦【参考方案2】:

如果您不介意导入json 模块,那么处理它的最佳方法是通过json.JSONDecodeError(或json.decoder.JSONDecodeError,因为它们是相同的),因为使用ValueError 之类的默认错误也可以捕获其他的异常不一定和json解码有关。

from json.decoder import JSONDecodeError


try:
    qByUser = byUsrUrlObj.read()
    qUserData = json.loads(qByUser).decode('utf-8')
    questionSubjs = qUserData["all"]["questions"]
except JSONDecodeError as e:
    # do whatever you want

//编辑(2020 年 10 月):

正如@Jacob Lee 在评论中指出的那样,当 JSON 对象不是 strbytesbytearray 时,可能会引发基本的公共 TypeError。你的问题是关于JSONDecodeError,但在这里还是值得一提的;为了处理这种情况,但要区分不同的问题,可以使用以下方法:

from json.decoder import JSONDecodeError


try:
    qByUser = byUsrUrlObj.read()
    qUserData = json.loads(qByUser).decode('utf-8')
    questionSubjs = qUserData["all"]["questions"]
except JSONDecodeError as e:
    # do whatever you want
except TypeError as e:
    # do whatever you want in this case

【讨论】:

不幸的是,当 JSON 对象不是 str、bytes 或 bytearray 时,json.loads 会引发 TypeError。这让我最近有点吃惊,因为我认为 JSONDecodeError 处理了这些情况,例如当 json.loads 的参数最终为 None 时。 @JacobLee:谢谢。最初的问题是关于处理JSONDecodeError 的最佳方法,所以我只关注那个,但你是对的,这个案例绝对值得一提。我已将其添加到答案中。

以上是关于无返回时处理 JSON 解码错误的主要内容,如果未能解决你的问题,请参考以下文章

Python 请求返回 JSON 解码器错误

PHP函数:json_last_error

使用无控制台和无调试选项时,可执行文件上的 Pyinstaller 编解码器错误

iOS JSON解码数字类型错误

Plot.ly API 在创建图形时随机抛出 JSON 解码错误

Ext JS 5 关于Store load返回json错误信息或异常的处理