json.loads能否忽略多余的逗号?
在这个StackOverflow问题中提到,JSON格式中是不允许有多余的逗号的。比如,这段代码
{
"key1": "value1",
"key2": "value2"
}
是正确的,但这段代码
{
"key1": "value1",
"key2": "value2",
}
就不符合语法规则。
而在另一个StackOverflow问题中提到的原因是,在Python代码中使用多余的逗号是合法的(甚至可能是被鼓励的?)。我同时在使用Python和JSON,所以我希望在这两种文件中保持一致性。有没有办法让json.loads
忽略多余的逗号呢?
8 个回答
用 python-rapidjson 解决问题很简单:
(这特别适合在 VSCode 的 settings.json
或类似文件上进行脚本编写,因为这些文件经常会生成或容忍无效的 JSON、JSON 中的注释等。)
import rapidjson
# From string: use rapidjson.loads
rapidjson.loads(
raw_string, parse_mode=rapidjson.PM_COMMENTS | rapidjson.PM_TRAILING_COMMAS
)
# From file: use rapidjson.load
rapidjson.load(
"file.json", parse_mode=rapidjson.PM_COMMENTS | rapidjson.PM_TRAILING_COMMAS
)
在传递这个值之前,先把逗号去掉。
import re
def clean_json(string):
string = re.sub(",[ \t\r\n]+}", "}", string)
string = re.sub(",[ \t\r\n]+\]", "]", string)
return string
在Python中,你可以在字典和列表的末尾加上逗号,所以我们可以利用这个特性来使用ast.literal_eval:
import ast, json
str = '{"key1": "value1", "key2": "value2",}'
python_obj = ast.literal_eval(str)
# python_obj is {'key1': 'value1', 'key2': 'value2'}
json_str = json.dumps(python_obj)
# json_str is '{"key1": "value1", "key2": "value2"}'
不过,JSON并不完全等同于Python,所以有一些特殊情况需要注意。例如,像null、true、false这样的值在Python中是不存在的。我们可以在执行eval之前,把这些值替换成Python中有效的对应值:
import ast, json
def clean_json(str):
str = str.replace('null', 'None').replace('true', 'True').replace('false', 'False')
return json.dumps(ast.literal_eval(str))
不过,这样做会不幸地把任何包含null、true或false这些词的字符串搞混。
{"sentence": "show your true colors"}
会变成
{"sentence": "show your True colors"}
快进到2021年,现在我们有了https://pypi.org/project/json5/
以下是链接中的一句话:
这是一个Python实现的JSON5数据格式。
JSON5在JSON数据交换格式的基础上进行了扩展,使其作为配置语言时更易用:
- 支持JavaScript风格的注释(包括单行和多行注释)。
- 对象的键可以不加引号,只要它们是合法的ECMAScript标识符。
- 对象和数组可以以逗号结尾。
- 字符串可以用单引号包裹,并且支持多行字符串。
使用方法和Python自带的json模块一致:
>>> import json5
>>> json5.loads('{"key1": "{my special value,}",}')
{u'key1': u'{my special value,}'}
不过它有个警告:
已知问题
- 我提到过它很慢吗?
不过对于加载启动配置等来说,它的速度还是够用的。
你可以用 jsoncomment 来包装 Python 的 JSON 解析器。
JSON Comment 允许你解析 JSON 文件或字符串,支持以下功能:
- 单行和多行注释
- 多行数据字符串
- 在对象和数组的最后一个项目后面可以有多余的逗号
使用示例:
import json
from jsoncomment import JsonComment
with open(filename) as data_file:
parser = JsonComment(json)
data = parser.load(data_file)