Python json.loads是否可以忽略尾随的逗号?
如中所述,json中不允许有任何尾随逗号。比如说这个,Python json.loads是否可以忽略尾随的逗号?,python,json,python-2.7,Python,Json,Python 2.7,如中所述,json中不允许有任何尾随逗号。比如说这个, { "key1": "value1", "key2": "value2" } 很好,但是这个 { "key1": "value1", "key2": "value2", } 是无效语法 出于中提到的原因,在Python代码中使用尾随逗号是合法的(也许是受鼓励的)。我同时使用Python和JSON,因此我希望能够在这两种类型的文件中保持一致。有没有办法让json.load忽略尾随的逗号?在传入值之前去掉逗号
{
"key1": "value1",
"key2": "value2"
}
很好,但是这个
{
"key1": "value1",
"key2": "value2",
}
是无效语法
出于中提到的原因,在Python代码中使用尾随逗号是合法的(也许是受鼓励的)。我同时使用Python和JSON,因此我希望能够在这两种类型的文件中保持一致。有没有办法让
json.load忽略尾随的逗号?在传入值之前去掉逗号
import re
def clean_json(string):
string = re.sub(",[ \t\r\n]+}", "}", string)
string = re.sub(",[ \t\r\n]+\]", "]", string)
return string
您可以使用
JSON注释允许使用以下内容解析JSON文件或字符串:
- 单行和多行注释
- 多行数据字符串
- 对象和数组中的尾随逗号,位于最后一项之后
用法示例:
import json
from jsoncomment import JsonComment
with open(filename) as data_file:
parser = JsonComment(json)
data = parser.load(data_file)
在python中,您可以在字典和列表中使用尾随逗号,因此我们应该能够使用ast.literal\u 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,因此有一些边缘情况。例如,python中不存在null、true、false等值。在运行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"}
将其他几个答案中的知识拼凑在一起,特别是使用@Porkbutts答案中的literal\u eval
的想法,我提出了一个非常邪恶的解决方案
def json_cleaner_加载程序(路径):
开放(路径)为fh时:
exec(“null=None;true=true;false=false;d={}”。格式(fh.read())
返回局部变量()[“d”]
这是通过在将JSON结构作为Python代码计算之前,将缺少的常量定义为它们的Python值来实现的。然后可以从locals()
(这是另一个字典)访问该结构
这应该适用于Python2.7和Python3.x
注意这将执行传递文件中的任何内容,Python解释器可以执行任何操作,因此它应该仅用于已知安全的输入上(即不要让web客户端提供内容),并且可能不用于任何生产环境。
如果提供了大量内容,则可能也会失败。使用
快进到2021年,现在我们有了
链接中的引用:
JSON5数据格式的Python实现
JSON5扩展了JSON数据交换格式,使其稍微
更可用作配置语言:
- JavaScript风格的注释(单行和多行)是合法的
- 如果对象键是合法的ECMAScript标识符,则可以不加引号
- 对象和数组可能以尾随逗号结尾
- 字符串可以是单引号,可以是多行字符串文字
允许
用法与python内置的json模块一致:
>>> import json5
>>> json5.loads('{"key1": "{my special value,}",}')
{u'key1': u'{my special value,}'}
它确实有一个警告:
已知问题
- 我有没有提到它很慢
加载启动配置等足够快。如果我没有选择使用任何外部模块,我的典型方法是首先清理输入(即删除尾随的逗号和注释),然后使用内置JSON解析器
下面是一个示例,它使用三个正则表达式剥离单行和多行注释,然后在JSON输入字符串上添加逗号,然后将其传递给内置的JSON.loads
方法
#/usr/bin/env python
导入json、re、sys
未筛选的_json_字符串=“”
{
“姓名”:“格雷森”,
“年龄”:45岁,
“汽车”:“A3”,
“旗帜”:假,
“默认”:true,
“条目”:[/“这是注释的开头,带有一些引号。”“”
红色,//这是另一条评论。“”
null,/*这是一个多行注释//
“这是另一行的引文。”
*/
假,,
是的,
],
“对象”:{
“键3”:空,
“key2”:“这是一个带有一些注释字符的字符串//**///”,
“key1”:false,
},
}
'''
RE\u SINGLE\u LINE\u COMMENT=RE.compile(r'(“(?:(?=(\\?))\2.*?”)|(?:\/{2,}.*))
RE\u MULTI\u LINE\u COMMENT=RE.compile(r'(“(?:(?=(\\?)\2.)*?”)(?:\/\*(?:(?!!\*\/)+\*/)”,flags=RE.M | RE.DOTALL)
RE_training_COMMA=RE.compile(r',(?=\s*?[\}\]]))
如果系统版本信息<(3,5):
#对于3.5之前的Python版本,请使用re.sub的补丁副本。
#基于https://gist.github.com/gromgull/3922244
def patched_re_sub(模式、应答、字符串、计数=0、标志=0):
def_repl(m):
类匹配():
定义初始值(self,m):
self.m=m
self.string=m.string
def组(自身,n):
返回m.组(n)或“”
返回重新展开(模式、匹配(m)、复制)
返回re.sub(模式、应答、字符串、计数=0、标志=0)
filtered_json_string=patched_re_sub(re_SINGLE_LINE_COMMENT,r'\1',unfiltered_json_string)
filtered_json_string=修补的_re_sub(re_多行_注释,r'\1',filtered_json_string)
其他:
filtered_json_string=RE_SINGLE_LINE_COMMENT.sub(r'\1',unfiltered_json_string)
filtered_json_string=RE_MULTI_LINE_COMMENT.sub(r'\1',filtered_json_string)
filtered_json_string=RE_training_COMMA.sub(“”,filtered_json_string)
json\u data=json.loads(过滤的\u json\u字符串)
打印(json.dumps(json_数据,缩进=4,排序_键=True))
简而言之,不是。一种语言的最佳实践或首选方法与另一种语言的最佳实践没有任何关系。在JSON中,它是无效的,因此,JSON解析器会将其报告为无效格式(正确行为!)。如果是Python字典,您可以使用ast.literal\u eval
对其进行解析。我不这么认为。json模块遵循标准。不过,您可能可以修改自己的版本。”
>>> import json5
>>> json5.loads('{"key1": "{my special value,}",}')
{u'key1': u'{my special value,}'}