【json异常】json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes

异常介绍

异常内容

json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes

出现原因

这个错误一般是由于在解析json的字符串的时候,提供的字符串不符合规范而导致的。根据json的格式要求,其属性名必须使用双引号("),不可以使用单引号(')

这里有的使用者可能非常困惑,凭什么json不允许使用单引号呢?这不合理,应该允许使用单引号才对!但是,json的规范就是这样规定的,这可能是考虑到一致性,可移植,或者单纯就是历史原因(最早json源自于javascript的对象字面量,实际上javascript最初就是规定应该使用双引号的,虽然现在你使用单引号其实也是可以的)

总而言之,因为标准的json就有这样的要求,因此你不应当,也不可以在标准json中,为属性名提供单引号

异常代码示例

import json

s = "{'name': 'wuming', 'age': 18}"

r = json.loads(s)

print(r)

解决方案

直接修改

既然我们已经知道了,这个异常是由于不正确的使用了单引号导致的,因此只要规范的使用json格式,将其中属性名的单引号改为双引号,就可以解决这个问题了

比如说,将之前的代码做如下的修改

import json

s = '{"name": "wuming", "age": 18}'

r = json.loads(s)

print(r)

可以看到,我们的问题已经被解决了。当前,json可以正确的解析我们的字符串了

如果无法修改

对于直接修改的方式,有的人会提出新的疑问:这个字符串不是我提供的,是别人给我的,他就是这种格式的,我就得使用这种格式的字符串,没有办法做到自己一点点全都修改啊,那怎么办呢?

实际上,这种场景也是非常常见的,尤其是在爬虫的程序中,可能你爬到的数据,就是类似于json,但不是标准的json格式,此时还必须得利用这种非标准格式,那么该怎么办呢?

这个时候其实也很简单,如果我们一定要使用这种格式的字符串,可以考虑不要使用json,而是使用其他的方式解析这个字符串

from ast import literal_eval

s = "{'name': 'wuming', 'age': 18}"
r = literal_eval(s)
print(r)

这种方式,就可以将我们之前的非标准的json字符串,解析为python的数据类型了。至于ast.literal_eval的方法,它的功能类似于eval,但是相比eval更加的安全,因此推荐这样使用

那么,如果你还是希望使用json怎么办呢?也不要紧,我们可以在读取为python的数据类型以后,再通过json模块,将我们的数据类型,重新保存为json就可以了,这样一来,我们就可以将其转换为标准的json数据格式了

import json
from ast import literal_eval

s = "{'name': 'wuming', 'age': 18}"
r = literal_eval(s)

new_s = json.dumps(r)

print(new_s)

此时,我们可以将转换过后的新的标准的json格式保存下来,以供后续使用,这样再下次由于我们已经是标准的json字符串了,就可以直接通过json.loads读取,而不会再出现之前的错误了

特殊情况注意

使用literal_eval的方法,虽然能够解决大多数情况下的非标准字符串的问题,但是还是要小心,在极端的情况下,可能无法完成解析,比如说

import json

s = {"id": 1, "is_admin": False, "is_login": True, "phone": None}

r = json.dumps(s)

print(r) # 在保存为json格式的时候,该内容会保存为{"id": 1, "is_admin": false, "is_login": true, "phone": null}

可以看到,在json中使用的true,false和null,对应的是python中的True,False和None,但是如果直接使用literal_eval解析的话

import json

s = {"id": 1, "is_admin": false, "is_login": true, "phone": null}
r = literal_eval(s)

new_s = json.dumps(r)

print(new_s)

这是无法完成正常解析的,会报错新的异常NameError: name 'false' is not defined,在这种情况下应该额外注意,比如说使用替换的方式,将json中的特殊值,转为能够正确使用的python值,这样才能够正确的使用。这里可以通过字符串的操作函数,提供一个简单的替换方式

from ast import literal_eval

s = '{"id": 1, "is_admin": false, "is_login": true, "phone": null}'
s = s.replace("null", "None").replace("false", "False").replace("true", "True")

r = literal_eval(s)
print(r)

可以看到,现在我们的字符串可以被正常解析了。但是呢,还是需要注意,如果在特别极端的情况下,你的数据中还包括了字符串形式的"true",会导致字符串形式的"true"被错误的替换。虽然这种情况可能是比较罕见的,但如果真的遇到的话,还需要根据你的实际情况,适当的进行修改

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值