漂亮打印 JSON dumps

42

我使用这段代码将一个dict格式化输出为JSON:

import json
d = {'a': 'blah', 'b': 'foo', 'c': [1,2,3]}
print json.dumps(d, indent = 2, separators=(',', ': '))

输出:

{
  "a": "blah",
  "c": [
    1,
    2,
    3
  ],
  "b": "foo"
}

这有点过了(每个列表元素都要换行!)。

使用哪种语法可以得到这个结果:

{
  "a": "blah",
  "c": [1, 2, 3],
  "b": "foo"
}

改为什么?


2
这并不是你问题的确切答案,但如果你只是在寻找一种易于阅读的数据格式,那么你可以尝试使用YAML。对于诸如列表和字典之类的集合,YAML有两种语法,一种是“块”语法(其中缩进显示嵌套),另一种是“流”语法(其中方括号完成该任务)。默认情况下,PyYAML的输出将使用“流”语法来呈现不包含其他容器的列表和字典,这似乎正是你想要的漂亮打印输出。 - Blckknght
另外一点说明:我想避免将其转换为字符串,因为当我将JSON文件load回到dict中时,如果它是一个字符串,我就无法再访问list了(或者我需要将字符串解析成列表,但这很糟糕,不应该这样做...) - Basj
1
@Basj:我并不是一个YAML专家,但我的理解是它非常稳定和成熟,尽管没有JSON被广泛使用。你可以在官方YAML网站找到其标准,但是Wikipedia页面似乎更好地概述了它。JSON是最新版本YAML的子集(与早期YAML版本的不兼容性显然很少遇到)。 - Blckknght
如果列表中包含字典或另一个列表等,缩进方面应该如何处理? - martineau
据我所知,使用内置的JSONEncoder类直接进行子类化或甚至猴子补丁都无法满足您的要求,因此似乎没有合理的方法来完成这个任务。因此,您可能需要像@Shan Valleru建议的那样编写自己的代码。 - martineau
显示剩余6条评论
6个回答

28

我最终使用了 jsbeautifier:

import jsbeautifier
opts = jsbeautifier.default_options()
opts.indent_size = 2
jsbeautifier.beautify(json.dumps(d), opts)

输出:

{
  "a": "blah",
  "c": [1, 2, 3],
  "b": "foo"
}

6

另一种替代方案是 print(json.dumps(d, indent=None, separators=(',\n', ': ')))

输出结果将会是:

{"a": "blah",
"c": [1,
2,
3],
"b": "foo"}

请注意,尽管在https://docs.python.org/2.7/library/json.html#basic-usage的官方文档中说默认参数是separators=None,但实际上这意味着“使用默认值separators=(', ',': ')”。此外,请注意逗号分隔符不区分k/v对和列表元素。

1
谢谢,但这并不是我们需要的准确内容;我们希望将 [1, 2, 3] 写在一行上。 - Basj
没错,它并不完美,但与其他庞然大物相比,它是精简而高效的。 ;) 如果我想要变得花哨一些,我会使用 https://pypi.python.org/pypi/jq/ - MarkHu
1
感谢分隔符,帮助我实现了Lua的兼容性。在Lua中不允许使用空格。 - josifoski

6

多年以后,我发现内置的 pprint 模块提供了解决方案:

import pprint
d = {'a': 'blah', 'b': 'foo', 'c': [1,2,3]}
pprint.pprint(d)                    # default width=80 so this will be printed in a single line
pprint.pprint(d, width=20)          # here it will be wrapped exactly as expected

输出:

{'a': 'blah',  
 'b': 'foo',  
 'c': [1, 2, 3]}


3
这不一定是有效的JSON格式,这只是一个漂亮打印的Python字典,通常可以作为有效的JSON。 - Anonymous
@Anonymous 你说得对,但请注意我的问题明确是关于漂亮打印的,而不是关于有效的JSON字符串。 - Basj
虽然您的问题意图可能不是关于创建有效的JSON字符串,但由于标题等原因,它看起来像是这样。单引号绝对不是有效的JSON。所以这是关于漂亮地打印一个字典,而不是关于漂亮地打印JSON? - t.niese

0

我无法让jsbeautifier起作用,所以我使用了正则表达式。JSON模式如下:

'{\n    "string": [\n        4,\n        1.0,\n        6,\n        1.0,\n        8,\n        1.0,\n        9,\n        1.0\n    ],\n...'

我想要的是

'{\n    "string": [ 4, 1.0, 6, 1.0, 8, 1.0, 9, 1.0],\n'

所以

t = json.dumps(apriori, indent=4)
t = re.sub('\[\n {7}', '[', t)
t = re.sub('(?<!\]),\n {7}', ',', t)
t = re.sub('\n {4}\]', ']', t)
outfile.write(t)

所以,我不是只有一个“dump(apriori, t, indent=4)”,而是有了这5行代码。

2
欢迎 @ChrisChang 来到 StackOverflow!这似乎更像是一个新问题,而不是对当前问题的回答。您可以将其发布为新问题吗? - Basj
嗨@Basj,谢谢。这是对根问题(Pretty Print JSON Dumps)的回答,但我参考了Allen Z关于jsbeautifier的帖子。也许我应该把回复放在他的答案中,但对jsbeautifier的评论是离题的。 - user15118385

-2

这个问题困扰了我一段时间,但我找到了一个几乎让我满意的一行代码:

print json.dumps(eval(str(d).replace('[', '"[').replace(']', ']"').replace('(', '"(').replace(')', ')"')), indent=2).replace('\"\\"[', '[').replace(']\\"\"', ']').replace('\"\\"(', '(').replace(')\\"\"', ')')

这个程序本质上是将所有的列表或元组转换为字符串,然后使用json.dumps和缩进来格式化字典。然后你只需要删除引号就可以了!

注意:我将字典转换为字符串是为了方便地转换所有嵌套字典中的列表/元组。

PS. 我希望Python警察不会因为我使用eval而追捕我...(请谨慎使用)


-3

也许不够高效,但考虑一个更简单的情况(在Python 3中进行了一些测试,但在Python 2中也可能适用):

def dictJSONdumps( obj, levels, indentlevels = 0 ):
    import json
    if isinstance( obj, dict ):
        res = []
        for ix in sorted( obj, key=lambda x: str( x )):
            temp = ' ' * indentlevels + json.dumps( ix, ensure_ascii=False ) + ': '
            if levels:
                temp += dictJSONdumps( obj[ ix ], levels-1, indentlevels+1 )
            else:
                temp += json.dumps( obj[ ix ], ensure_ascii=False )
            res.append( temp )
        return '{\n' + ',\n'.join( res ) + '\n}'
    else:
        return json.dumps( obj, ensure_ascii=False )

这可能会给你一些想法,但不用完全编写自己的序列化器。我使用了自己喜欢的缩进技术,并硬编码了ensure_ascii,但你可以添加参数并将它们传递,或者硬编码自己的参数等。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接