Python:当没有返回时处理JSON解码错误

add*_*ons 57 python json python-3.x

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

{
"all" : {
    "count" : 0,
    "questions" : [     ]
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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)
Run Code Online (Sandbox Code Playgroud)

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

Tad*_*eck 120

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'
Run Code Online (Sandbox Code Playgroud)

编辑:因为simplejson.decoder.JSONDecodeError实际上继承自ValueError(在这里证明),我通过使用简化了catch语句ValueError.

  • 你应该总是捕获正确的异常.否则,如果存在实际的`ValueError`异常,或者某些其他异常也继承自`ValueError`,您可能会错过代码中的错误. (8认同)
  • @JulieinAustin:我会这样做,因为它实际上是...标准库.如果你不关心速度_too,我会使用现有的.是的,`simplejson`以更细粒度的方式完成此任务,但它有自己的问题.如果`try ... except`块只会封装`json.loads`调用,你会怎么说?我认为这会更好,但需要一些锅炉来满足要求(例如,将异常的类更改为更细粒度的东西,但不要试图在这里拯救世界). (3认同)
  • `ValueError`过于宽泛,无法在此上下文中使用.在用户代码方面`qUserData ["all"] ["questions"]`我也可以抛出`ValueError`.更不用说在`simplejson`中的其他位置引发`ValueError`.当事情开始"无缘无故"时,这种事情可能会让你在6个月的时间里真的很难受. (3认同)
  • @JulieinAustin:问题在于,在这种情况下,您确实没有太多选择-stdlib的json模块引发ValueError。 (2认同)
  • 然后我会远离那个解码器.最初的问题是关于`simplejson`模块,它确实在错误的输入上引发了`JSONDecodeError`.请参阅您之前的链接. (2认同)

pes*_*on2 17

如果您不介意导入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
Run Code Online (Sandbox Code Playgroud)

//编辑(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
Run Code Online (Sandbox Code Playgroud)