我有一个json文件,如下所示:
{
"author":"John",
"desc": "If it is important to decode all valid JSON correctly \
and speed isn't as important, you can use the built-in json module, \
orsimplejson. They are basically the same but sometimes simplej \
further along than the version of it that is included with \
distribution."
//"birthday": "nothing" //I comment this line
}
Run Code Online (Sandbox Code Playgroud)
此文件由另一个程序自动创建.我如何用Python解析它?
小智 9
jsoncomment很好,但不支持内联注释.
查看jstyleson,哪个支持
pip install jstyleson
import jstyleson
result_dict = jstyleson.loads(invalid_json_str) # OK
jstyleson.dumps(result_dict)
Run Code Online (Sandbox Code Playgroud)
我没有亲自使用它,但是jsoncomment python 包支持解析带有注释的JSON文件。
您可以使用它代替 JSON 解析器,如下所示:
parser = JsonComment(json)
parsed_object = parser.loads(jsonString)
Run Code Online (Sandbox Code Playgroud)
我建议大家改用 JSON5 库。JSON5 是具有 JavaScript 功能/支持的 JSON。它是世界上最流行的 JSON 语言扩展。它有注释,支持对象/数组中的尾随逗号,支持单引号键/字符串,支持不带引号的对象键等。并且有适当的解析器库和深度测试套件,一切正常。
有两种不同的高质量 Python 实现:
https://github.com/dpranke/pyjson5(完全用 Python 编写,速度很慢,有自己的测试套件,项目始于 2015 年,更“喜欢”)。PyPi 页面:https ://pypi.org/project/json5/
推荐: https : //github.com/Kijewski/pyjson5(使用通过 Cython 编译的本地代码,速度更快,使用官方 json5 js 测试套件而不是自己的,项目于 2018 年启动)。PyPi 页面:https ://pypi.org/project/pyjson5/
这是 JSON5 规范:https ://json5.org/
改进之前的答案,以便在删除行的情况下提供正确的行号支持:
import json
class JSONWithCommentsDecoder(json.JSONDecoder):
def __init__(self, **kw):
super().__init__(**kw)
def decode(self, s: str) -> Any:
s = '\n'.join(l if not l.lstrip().startswith('//') else '' for l in s.split('\n'))
return super().decode(s)
your_obj = json.load(f, cls=JSONWithCommentsDecoder)
Run Code Online (Sandbox Code Playgroud)
此实现通过用空行替换注释行而不是完全删除它来稍微改进了前面的答案,因为这会破坏行数。
我无法想象一个json文件"由其他程序自动创建"将包含注释.因为json规范根本没有定义任何注释,这是设计的,所以没有json库会输出带注释的json文件.
这些评论通常是后来由人类添加的.在这种情况下也不例外.OP在他的帖子中提到://"birthday": "nothing" //I comment this line
.
所以真正的问题应该是,如何正确评论json文件中的某些内容,同时保持其与规范的兼容性,从而与其他json库兼容?
答案是,将您的字段重命名为另一个名称.例:
{
"foo": "content for foo",
"bar": "content for bar"
}
Run Code Online (Sandbox Code Playgroud)
可以改成:
{
"foo": "content for foo",
"this_is_bar_but_been_commented_out": "content for bar"
}
Run Code Online (Sandbox Code Playgroud)
这在大多数情况下都会正常工作,因为消费者很可能会忽略意外字段(但并非总是如此,这取决于您的json文件使用者的实现.所以YMMV.)
更新:显然有些读者不高兴,因为这个答案没有给出他们期望的"解决方案".嗯,事实上,我确实提供了一个有效的解决方案,通过隐式链接到JSON设计师的引用:
Douglas Crockford Public 2012年4月30日评论JSON
我从JSON中删除了注释,因为我看到有人使用它们来保存解析指令,这种做法会破坏互操作性.我知道缺乏评论会让一些人感到悲伤,但事实并非如此.
假设您使用JSON来保留要注释的配置文件.继续,插入您喜欢的所有评论.然后通过JSMin将其传递给JSON解析器.
所以,是的,继续使用JSMin.请记住,当您前往"使用JSON中的注释"时,这是一个概念上未知的领域.无法保证您选择的任何工具都可以处理:内联[1,2,3,/* a comment */ 10]
,Python样式[1, 2, 3] # a comment
(这是Python中的注释但不是Javascript中的注释),INI样式[1, 2, 3] ; a comment
,......,您可以理解.
我仍然建议不要首先在JSON中添加不符合要求的注释.
小智 5
对于 [95%] 的情况,当您只需要简单的引导行//
注释和简单的方法来处理它们时:
import json
class JSONWithCommentsDecoder(json.JSONDecoder):
def __init__(self, **kw):
super().__init__(**kw)
def decode(self, s: str) -> Any:
s = '\n'.join(l for l in s.split('\n') if not l.lstrip(' ').startswith('//'))
return super().decode(s)
your_obj = json.load(f, cls=JSONWithCommentsDecoder)
Run Code Online (Sandbox Code Playgroud)