【Python】JSONDecodeError: Expecting value: line 1 column 1 (char 0)



问题

代码执行抛出异常:JSONDecodeError: Expecting value: line 1 column 1 (char 0)



原因

代码中使用了 json.loads 来将 JSON 数据解析成 Python 数据类型:

import json

...many codes...

data = json.loads(resp.text)

但是因为传递给 json.loads 的参数不符合 JSON 格式,所以抛出异常。

不符合 JSON 格式的原因参见的有:

  • 键值对使用单引号而非双引号。
  • 参数为普通的字符串格式(plain or html)。

以下是 duplicate 演示:

n/a



Solution

关于 text == """{"foo": 'egg'}""" 这样的格式错误问题,假设 text 是来自REST API 的请求响应,那么原则上来讲应该是服务器软件的问题。所以这里不再多言。

另外一种便是通过 REST API GET 或 POST 等等到的 text,因为可能存在失败的情况,而有的失败的 response 是普通的 HTML 格式。所以不能不做区分地 .loads

这里是一处我原先错误的写法:

import json
import requests
from requests.exceptions import HTTPError

...codes...

def foo():
    try:
        r = requests.get(url, headers=headers)
        print("[debug] json.loads(r.text): ", json.loads(r.text))
        r.raise_for_status()
    except HTTPError as err:
        raise
    return json.loads(r.text)

这样就会造成 JSONDecodeError 的错误先于 HTTP 失败的 raise status 发生。
虽然目的是“不管失败还是成功,都打印响应消息”,但是没有意识到这个响应消息格式只有成功的时候才是 JSON 格式。

可以简单的将出现错误的 line 10 修改为:

        print("[debug] response content: ", r.text)

或者对成功或失败的 debug 输出做一下区分:

def foo():
    try:
        r = requests.get(url, headers=headers)
        r.raise_for_status()
    except HTTPError as err:
        print("[error] ({}): {}".format(r.status_code, r.text))
        raise
    else:
        print("[debug] json.loads(r.text): ", json.loads(r.text))
    return json.loads(r.text)



其它 JSONDecodeError

最后一行逗号

如:

{
    "foo": "bar",
    "egg": "spam",
}

这样的字符串用 json.loads 也是会抛出 JSONDecodeError 的:

...
JSONDecodeError: Expecting property name enclosed in double quotes: line 5 column 1 (char 40)

正确的写法是:

{
   "foo": "bar",
   "egg": "spam"
}

这是 JSON 的格式问题。如果字符串是错误的 JSON 语法格式,那么调用 json.loads 来 decode 就会抛出异常。



Reference



发布了164 篇原创文章 · 获赞 76 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/qq_29757283/article/details/98252728