没有返回任何内容时处理JSON解码错误


78

我正在解析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)

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


3
其实你有什么问题
塔德克2011年

您回答了问题;)好像我在真正键入问题之前就提交了问题。谢谢你的回答。
加分号

2
好的,我很高兴为您提供帮助-现在看起来像是心灵感应;)不过,感谢您提出问题。祝好运!
塔德克2011年

Answers:


150

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此处的证明)继承的,所以我只使用简化了catch语句ValueError


11
您应该始终捕获正确的异常。否则,如果存在实际的ValueError异常或从中继承的其他异常,您可能会错过代码中的错误ValueError
朱莉在奥斯丁

2
@JulieinAustin:问题在于,在这种情况下,您确实没有太多选择-stdlib的json模块引发ValueError。
塔德克2015年

2
然后,我将远离该解码器。最初的问题是关于simplejson模块的,JSONDecodeError在输入错误时确实会引起很多问题。请参阅您之前的链接。
朱莉在奥斯丁

3
@JulieinAustin:否则,我会这样做,因为它实际上是标准库。如果你不关心速度太多,我会用什么已经可用。是的,simplejson以更细粒度的方式做到这一点,但这有其自身的问题。如果该try...except块仅封装json.loads调用,您会说什么?我认为这样做会更好,但是需要一些锅炉位置来满足要求(例如,将异常的类别更改为更细粒度的内容,但不要在此处尝试拯救世界)。
塔德克2015年

3
ValueError在此情况下使用范围太广。就用户代码而言,我相信qUserData["all"]["questions"]也可能抛出ValueError。更不用说ValueError在其他地方的人了simplejson。当事情由于“无缘无故”而开始崩溃时,这种事情可能会在6个月的时间里给您带来
Anthony Manning-Franklin

10

如果您不介意导入该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李在评论指出,有可能是基本常识TypeError时引发JSON对象不是strbytesbytearray。您的问题是关于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时。
雅各布·李

1
@JacobLee:谢谢。最初的问题是关于处理该问题的最佳方法,JSONDecodeError所以我只关注那个问题,但是您是对的,这种情况绝对值得一提。我已将其添加到答案中。
pesekon2
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.