如何漂亮地打印JSON文件?

How to prettyprint a JSON file?

提问人:Colleen 提问时间:10/18/2012 最后编辑:Mateen UlhaqColleen 更新时间:10/22/2023 访问量:2162854

问:

如何在 Python 中漂亮地打印 JSON 文件?

python json 格式化 漂亮打印

评论


答:

2886赞 Blender 10/18/2012 #1

使用 json.dump() 或 json.dumps() 的参数指定缩进多少个空格:indent=

>>> import json
>>> your_json = '["foo", {"bar": ["baz", null, 1.0, 2]}]'
>>> parsed = json.loads(your_json)
>>> print(json.dumps(parsed, indent=4))
[
    "foo",
    {
        "bar": [
            "baz",
            null,
            1.0,
            2
        ]
    }
]

要解析文件,请使用 json.load():

with open('filename.txt', 'r') as handle:
    parsed = json.load(handle)

评论

232赞 Peterino 8/4/2014
对于简单的漂亮打印,这也可以在没有显式解析的情况下工作:print json.dumps(your_json_string, indent=4)
23赞 krs013 3/17/2016
没有缩进,你只会得到一行丑陋的文字,这就是我来这里的原因。
6赞 Christophe Roussy 5/31/2016
这类似于此处讨论的 JavaScript stackoverflow.com/questions/4810841/...var str = JSON.stringify(obj, null, 4);
5赞 ACV 7/3/2021
@Peterino,如果没有显式解析,它就无法工作。它打印转义行
0赞 Peterlits Zo 2/22/2022
在 JS 工具 prettier 中,如果线宽小于 80,则不会添加“换行符”。我正在寻找它。
471赞 Gismo Ranas 8/26/2015 #2

您可以在命令行上执行此操作:

python3 -m json.tool some.json

(正如在问题的评论中已经提到的,感谢 @Kai Petzke 的 python3 建议)。

实际上,就命令行上的json处理而言,python并不是我最喜欢的工具。对于简单来说,漂亮的打印是可以的,但是如果你想操作json,它可能会变得过于复杂。你很快就需要编写一个单独的脚本文件,你最终可能会得到一个键是“某个键”(python unicode)的地图,这使得选择字段变得更加困难,并且并没有真正朝着漂亮的打印方向发展。

你也可以使用 jq

jq . some.json

你会得到颜色作为奖励(并且更容易扩展)。

附录:一方面使用 jq 处理大型 JSON 文件,另一方面使用非常大的 jq 程序,在评论中存在一些混淆。为了漂亮地打印由单个大型 JSON 实体组成的文件,实际限制是 RAM。对于由单个真实世界数据数组组成的 2GB 文件进行漂亮打印,漂亮打印所需的“最大驻留集大小”为 5GB(无论是使用 jq 1.5 还是 1.6)。另请注意,jq 可以在 python 中使用。pip install jq

评论

5赞 Chris McKee 5/17/2016
JQ 很棒,但有一个最大限制,所以它对大文件毫无用处。(即处理一个 1.15mb 的文件会爆炸)github.com/stedolan/jq/issues/1041
13赞 Gismo Ranas 5/17/2016
是的,伙计,当然,如果你正在用超过 10K 行代码编写 jq 过滤器,我认为你正在尝试骑自行车去火星之类的事情。
3赞 Chris McKee 5/17/2016
lol :D @gismo-ranas 通过管道传输到文件的 json.tool 版本在大文件上运行得非常好;而且速度快得惊人。我喜欢 JQ,但是格式化任何超出小有效载荷(您可以在大多数文本编辑器中执行)的内容都超出了它的能力范围:)随机添加:json-generator.com 是制作测试数据的简洁工具
8赞 fatal_error 12/10/2016
或者只是:jq '' < some.json
4赞 Kai Petzke 1/21/2019
实际上,我强烈建议使用 ,因为这会保留 JSON 字典中字段的原始顺序。python 解释器版本 2 按字母升序对字段进行排序,这通常不是您想要的。python3 -m json.tool <IN >OUT
63赞 Shubham Chaudhary 8/27/2015 #3

Pygmentize 是一个强大的工具,用于为终端命令的输出着色。

下面是使用它向输出添加语法突出显示的示例:json.tool

echo '{"foo": "bar"}' | python -m json.tool | pygmentize -l json

结果将如下所示:

demo

之前的 Stack Overflow 答案中,我详细介绍了如何安装和使用 .pygmentize

评论

4赞 Denis The Menace 1/29/2018
在您的示例中实际上不起作用;)由于输入来自 stdin,因此 pygmentize 无法做出很好的猜测。您需要显式指定词法分析器:-gecho '{"foo": "bar"}' | python -m json.tool | pygmentize -l json
2赞 Shubham Chaudhary 1/30/2018
@DenisTheMenace 它曾经在 2015 年创建此示例图像时工作。它现在似乎也不能在我的系统上运行。
47赞 zelusp 6/11/2016 #4

使用这个函数,不要费力地记住你的 JSON 是否是 or - 看看漂亮的印刷品:strdict

import json

def pp_json(json_thing, sort=True, indents=4):
    if type(json_thing) is str:
        print(json.dumps(json.loads(json_thing), sort_keys=sort, indent=indents))
    else:
        print(json.dumps(json_thing, sort_keys=sort, indent=indents))
    return None

pp_json(your_json_string_or_dict)

评论

0赞 Karl Knechtel 1/27/2023
这似乎只是在现有答案上放置了一个很好的界面,并没有真正参与问题的实质。这里的关键点是关键字参数的使用,这已经很好地涵盖了。除此之外,JSON 文档表示单个字符串是有效的。从应用逻辑推理开始,确定对输入使用哪种处理应该是程序员的责任——虽然 Python 旨在允许这种灵活性,但通常不鼓励进行显式类型检查和强制。indent
2赞 zelusp 1/28/2023
人们只想检查他们的 JSON,我的家伙。
0赞 Eamonn Kenny 6/20/2023
这是迄今为止最好的解决方案!JQ 非常适合命令行,但这是最好的编程解决方案。现在应该是最好的答案。
21赞 V P 3/28/2017 #5

为了能够从命令行进行漂亮的打印并能够控制缩进等,您可以设置类似于以下内容的别名:

alias jsonpp="python -c 'import sys, json; print json.dumps(json.load(sys.stdin), sort_keys=True, indent=2)'"

然后通过以下方式之一使用别名:

cat myfile.json | jsonpp
jsonpp < myfile.json

评论

0赞 Karl Knechtel 1/27/2023
该模块明确提供了避免对此类事情的需求。jsonjson.tool
146赞 ikreb 1/5/2018 #6

使用标准库模块读取数据后,使用 pprint 标准库模块显示解析后的数据。例:json

import json
import pprint

json_data = None
with open('file_name.txt', 'r') as f:
    data = f.read()
    json_data = json.loads(data)

# print json to screen with human-friendly formatting
pprint.pprint(json_data, compact=True)

# write json to file with human-friendly formatting
pretty_json_str = pprint.pformat(json_data, compact=True).replace("'",'"')

with open('file_name.json', 'w') as f:
    f.write(pretty_json_str)

默认值为 1,因此您可能需要指定自己的值。indent

默认情况下,pprint 将输出如下列表:

'not compact': ['pprint',
                'will',
                'output',
                'lists',
                'like',
                'this'],

这并不比指定的更好。json.dump()json.dumps()indent

使用 ,pprint 将输出如下列表:compact=True

'compact': ['pprint', 'with compact=True', 'will', 'output',
            'lists', 'like', 'this'],

请注意,您可以指定它将与参数一起包装的位置。width

有必要在 pprint.pformat() 返回的字符串中将“单引号”替换为“双引号”,因为单引号不是有效的 json。当您在文本编辑器中查看文件时,它可能无法正确突出显示 json。

无论如何,您可能希望将其保存为有效的 json,以便您可以作为人类舒适地阅读您的 json 文件,如果它们没有间距的格式化不是更重要的,以便它们可以以令人眼花缭乱的速度进行计算机处理。

最终,输出将如下所示:

{'address': {'city': 'New York',
             'postalCode': '10021-3100',
             'state': 'NY',
             'streetAddress': '21 2nd Street'},
 'age': 27,
 'children': [],
 'firstName': 'John',
 'isAlive': True,
 'lastName': 'Smith'}

评论

13赞 drevicko 6/29/2018
这样做的问题是 pprint 将交替使用单引号和双引号,但 json 只需要双引号,因此您的 pprinted json 可能不再解析为有效的 json。
11赞 ikreb 7/9/2018
是的,但它只是输出一个 json 文件。不获取输出并将其再次写入文件中。
2赞 erik258 11/11/2021
问题具体说要漂亮地打印一个 JSON 文件,而不是 JSON 文件的 Python 表示形式
3赞 Victor Schröder 9/7/2022
这个解决方案有很多问题,我什至无法开始。不能保证有效的 JSON,事实上,很多时候它根本不有效。它不仅会混淆所有引号,而且还会输出许多仅对 Python 有意义的字符串表示。、 、 各种对象,即使它们具有明确定义的 JSON 可序列化方式。将单引号替换为双引号只会使情况变得更糟,它甚至可能不再是有效的 Python,您只需要在任何字符串中使用双引号。pprintNonedatetime
4赞 Karl Knechtel 1/27/2023
作为编辑,我的工作不是纠正技术细节,但简单地将单引号换成双引号绝对不足以将输出(就像输出一样)转换为有效的 JSON,即使数据最初来自 JSON。简单的例子:对有效的文件内容(在 JSON 中表示包含反斜杠的字符串)进行往返将产生(既不是有效的 JSON 也不是有效的 Python 文字)。往返有效文件内容将生成一个包含 .pprint.pformatrepr"\"""""nullNone
9赞 David Liu 1/23/2018 #7

下面是一个简单的示例,在 Python 中以很好的方式将 JSON 打印到控制台,而无需将 JSON 作为本地文件放在您的计算机上:

import pprint
import json 
from urllib.request import urlopen # (Only used to get this example)

# Getting a JSON example for this example 
r = urlopen("https://mdn.github.io/fetch-examples/fetch-json/products.json")
text = r.read() 

# To print it
pprint.pprint(json.loads(text))

评论

2赞 Mr. T 1/23/2018
我在 Python 3 中收到以下错误消息:“TypeError:JSON 对象必须是 str,而不是'bytes'”
0赞 Karl Knechtel 1/27/2023
“不需要 JSON 作为本地文件放在您的计算机上:” - 不过,这个问题明确询问了文件。虽然展示如何从互联网来源获取数据可能对其他人有用,但这是一个单独问题相关的单独问题。(如果有人如何下载一个JSON文件并漂亮地打印出来,那会因为缺乏重点而被关闭;这显然是两个问题合二为一。碰巧的是,另一个问题已经得到了很好的涵盖。
23赞 Nakamoto 4/10/2019 #8

使用 pprint: https://docs.python.org/3.6/library/pprint.html

import pprint
pprint.pprint(json)

print()pprint.pprint()

print(json)
{'feed': {'title': 'W3Schools Home Page', 'title_detail': {'type': 'text/plain', 'language': None, 'base': '', 'value': 'W3Schools Home Page'}, 'links': [{'rel': 'alternate', 'type': 'text/html', 'href': 'https://www.w3schools.com'}], 'link': 'https://www.w3schools.com', 'subtitle': 'Free web building tutorials', 'subtitle_detail': {'type': 'text/html', 'language': None, 'base': '', 'value': 'Free web building tutorials'}}, 'entries': [], 'bozo': 0, 'encoding': 'utf-8', 'version': 'rss20', 'namespaces': {}}

pprint.pprint(json)
{'bozo': 0,
 'encoding': 'utf-8',
 'entries': [],
 'feed': {'link': 'https://www.w3schools.com',
          'links': [{'href': 'https://www.w3schools.com',
                     'rel': 'alternate',
                     'type': 'text/html'}],
          'subtitle': 'Free web building tutorials',
          'subtitle_detail': {'base': '',
                              'language': None,
                              'type': 'text/html',
                              'value': 'Free web building tutorials'},
          'title': 'W3Schools Home Page',
          'title_detail': {'base': '',
                           'language': None,
                           'type': 'text/plain',
                           'value': 'W3Schools Home Page'}},
 'namespaces': {},
 'version': 'rss20'}

评论

17赞 selurvedu 11/26/2019
pprint不生成有效的 JSON 文档。
0赞 Charlie Parker 2/10/2021
@selurvedu这意味着什么,为什么这很重要?
5赞 3/7/2021
@CharlieParker 我希望他们的意思是知道您有一个有效的 JSON 文档非常有用。当然,您可以使用该模块来处理数据,字典键对双引号或单引号字符串的工作方式相同,但某些工具,例如 Postman 和 JSON Editor Online,都希望键和值被双引号(根据 JSON 规范)。在任何情况下,json.org 都指定使用双引号,这不会产生。例如 生产。jsonpprintpprint.pprint({"name": "Jane"}){'name': 'Jane'}
3赞 Daniel F 7/28/2021
@CharlieParker一个例子是上面的结果,它应该是 .请注意 和 双引号。你要做的就是漂亮地打印一个 Python 对象。'language': None,"language": nullnull
0赞 selurvedu 11/9/2021
是的,这就是我的意思。感谢您的澄清。:-)
4赞 p3quod 4/26/2019 #9

我认为最好先解析json,以避免错误:

def format_response(response):
    try:
        parsed = json.loads(response.text)
    except JSONDecodeError:
        return response.text
    return json.dumps(parsed, ensure_ascii=True, indent=4)
10赞 Travis Clarke 10/2/2019 #10

你可以试试 pprintjson


安装

$ pip3 install pprintjson

用法

使用 pprintjson CLI 从文件中漂亮地打印 JSON。

$ pprintjson "./path/to/file.json"

使用 pprintjson CLI 从 stdin 漂亮地打印 JSON。

$ echo '{ "a": 1, "b": "string", "c": true }' | pprintjson

使用 pprintjson CLI 从字符串中漂亮地打印 JSON。

$ pprintjson -c '{ "a": 1, "b": "string", "c": true }'

从缩进量为 1 的字符串中漂亮地打印 JSON。

$ pprintjson -c '{ "a": 1, "b": "string", "c": true }' -i 1

漂亮的从字符串打印 JSON 并将输出保存到文件output.json。

$ pprintjson -c '{ "a": 1, "b": "string", "c": true }' -o ./output.json

输出

enter image description here

评论

0赞 Charlie Parker 2/10/2021
你的 soln 与 ?import pprint pprint.pprint(json)
0赞 TheTechRobo the Nerd 5/31/2021
@CharlieParker我认为它生成了一个有效的 json 文档,而不是使用单引号而不是双引号的 pprint
12赞 Pablo Emmanuel De Leo 10/11/2019 #11
def saveJson(date,fileToSave):
    with open(fileToSave, 'w+') as fileToSave:
        json.dump(date, fileToSave, ensure_ascii=True, indent=4, sort_keys=True)

它可以显示或保存到文件中。

评论

0赞 Karl Knechtel 1/27/2023
对于顶级答案来说,这似乎完全是多余的。
-10赞 Francisco Perdomo 4/1/2020 #12

它远非完美,但它可以完成工作。

data = data.replace(',"',',\n"')

你可以改进它,添加缩进等等,但如果你只是想能够读取一个更干净的JSON,这就是要走的路。

评论

0赞 AjayKumarBasuthkar 5/4/2021
AttributeError:“dict”对象没有属性“replace”
0赞 TheTechRobo the Nerd 2/11/2022
如果你的字符串中有逗号,这不会搞砸文件吗?
2赞 Karl Knechtel 1/27/2023
这甚至不能远程解决问题。即使在最好的情况下,输出看起来也不像 OP 想要的。
3赞 user 923227 11/13/2020 #13

我有一个类似的要求,即转储json文件的内容以进行日志记录,这既快速又简单:

print(json.dumps(json.load(open(os.path.join('<myPath>', '<myjson>'), "r")), indent = 4 ))

如果你经常使用它,那么把它放在一个函数中:

def pp_json_file(path, file):
    print(json.dumps(json.load(open(os.path.join(path, file), "r")), indent = 4))

评论

0赞 Karl Knechtel 1/27/2023
这到底增加了什么答案?一个特定的接口?
8赞 ntg 12/3/2022 #14

TL;DR:很多方法,也要考虑print(yaml.dump(j, sort_keys=False))

对于大多数用途,缩进应该这样做:

print(json.dumps(parsed, indent=2))

Json 结构基本上是树形结构。 在试图找到更花哨的东西时,我看到了这张漂亮的纸,上面描绘了其他形式的漂亮树木,这些树木可能很有趣:https://blog.ouseful.info/2021/07/13/exploring-the-hierarchical-structure-of-dataframes-and-csv-data/

它有一些交互式树,甚至还附带了一些代码,包括这个折叠树enter image description here

其他示例包括使用 plotly 以下是 plotly 的代码示例:

import plotly.express as px
fig = px.treemap(
    names = ["Eve","Cain", "Seth", "Enos", "Noam", "Abel", "Awan", "Enoch", "Azura"],
    parents = ["", "Eve", "Eve", "Seth", "Seth", "Eve", "Eve", "Awan", "Eve"]
)
fig.update_traces(root_color="lightgrey")
fig.update_layout(margin = dict(t=50, l=25, r=25, b=25))
fig.show()

enter image description here enter image description here

并使用 treelib。在这一点上,这个 github 也提供了很好的可视化效果。下面是一个使用 treelib 的示例:

#%pip install treelib
from treelib import Tree

country_tree = Tree()
# Create a root node
country_tree.create_node("Country", "countries")

# Group by country
for country, regions in wards_df.head(5).groupby(["CTRY17NM", "CTRY17CD"]):
    # Generate a node for each country
    country_tree.create_node(country[0], country[1], parent="countries")
    # Group by region
    for region, las in regions.groupby(["GOR10NM", "GOR10CD"]):
        # Generate a node for each region
        country_tree.create_node(region[0], region[1], parent=country[1])
        # Group by local authority
        for la, wards in las.groupby(['LAD17NM', 'LAD17CD']):
            # Create a node for each local authority
            country_tree.create_node(la[0], la[1], parent=region[1])
            for ward, _ in wards.groupby(['WD17NM', 'WD17CD']):
                # Create a leaf node for each ward
                country_tree.create_node(ward[0], ward[1], parent=la[1])

# Output the hierarchical data
country_tree.show()

enter image description here

基于此,我创建了一个函数来将 json 转换为树:

from treelib import Node, Tree, node

def create_node(tree, s, counter_byref, verbose, parent_id=None):
    node_id = counter_byref[0]
    if verbose:
        print(f"tree.create_node({s}, {node_id}, parent={parent_id})")
    tree.create_node(s, node_id, parent=parent_id)
    counter_byref[0] += 1
    return node_id

def to_compact_string(o):
    if type(o) == dict:
        if len(o)>1:
            raise Exception()
        k,v =next(iter(o.items()))
        return f'{k}:{to_compact_string(v)}'
    elif type(o) == list:
        if len(o)>1:
            raise Exception()
        return f'[{to_compact_string(next(iter(o)))}]'
    else:
        return str(o)

def to_compact(tree, o, counter_byref, verbose, parent_id):
    try:
        s = to_compact_string(o)
        if verbose:
            print(f"# to_compact({o}) ==> [{s}]")
        create_node(tree, s, counter_byref, verbose, parent_id=parent_id)
        return True
    except:
        return False

def json_2_tree(o , parent_id=None, tree=None, counter_byref=[0], verbose=False, compact_single_dict=False, listsNodeSymbol='+'):
    if tree is None:
        tree = Tree()
        parent_id = create_node(tree, '+', counter_byref, verbose)
    if compact_single_dict and to_compact(tree, o, counter_byref, verbose, parent_id):
        # no need to do more, inserted as a single node
        pass
    elif type(o) == dict:
        for k,v in o.items():
            if compact_single_dict and to_compact(tree, {k:v}, counter_byref, verbose, parent_id):
                # no need to do more, inserted as a single node
                continue
            key_nd_id = create_node(tree, str(k), counter_byref, verbose, parent_id=parent_id)
            if verbose:
                print(f"# json_2_tree({v})")
            json_2_tree(v , parent_id=key_nd_id, tree=tree, counter_byref=counter_byref, verbose=verbose, listsNodeSymbol=listsNodeSymbol, compact_single_dict=compact_single_dict)
    elif type(o) == list:
        if listsNodeSymbol is not None:
            parent_id = create_node(tree, listsNodeSymbol, counter_byref, verbose, parent_id=parent_id)
        for i in o:
            if compact_single_dict and to_compact(tree, i, counter_byref, verbose, parent_id):
                # no need to do more, inserted as a single node
                continue
            if verbose:
                print(f"# json_2_tree({i})")
            json_2_tree(i , parent_id=parent_id, tree=tree, counter_byref=counter_byref, verbose=verbose,listsNodeSymbol=listsNodeSymbol, compact_single_dict=compact_single_dict)
    else: #node
        create_node(tree, str(o), counter_byref, verbose, parent_id=parent_id)
    return tree

然后例如:

import json
j = json.loads('{"2": 3, "4": [5, 6], "7": {"8": 9}}')
json_2_tree(j ,verbose=False,listsNodeSymbol='+' ).show()  

给:

+
├── 2
│   └── 3
├── 4
│   └── +
│       ├── 5
│       └── 6
└── 7
    └── 8
        └── 9

json_2_tree(j ,listsNodeSymbol=None, verbose=False ).show()  
+
├── 2
│   └── 3
├── 4
│   ├── 5
│   └── 6
└── 7
    └── 8
        └── 9

json_2_tree(j ,compact_single_dict=True,listsNodeSymbol=None).show() 
+
├── 2:3
├── 4
│   ├── 5
│   └── 6
└── 7:8:9

正如你所看到的,人们可以根据他想要的明确程度和紧凑程度来制作不同的树。 我最喜欢的方法之一,也是最紧凑的方法之一,可能是使用 yaml

import yaml
j = json.loads('{"2": "3", "4": ["5", "6"], "7": {"8": "9"}}')
print(yaml.dump(j, sort_keys=False))

给出紧凑而明确的:

'2': '3'
'4':
- '5'
- '6'
'7':
  '8': '9'
7赞 unofficialdxnny 1/7/2023 #15

一个非常简单的方法是使用 rich。使用此方法,您还可以突出显示json

此方法从名为config.json

from rich import print_json

setup_type = open('config.json')
data = json.load(setup_type)
print_json(data=data)

最终输出将如下所示。enter image description here

评论

0赞 Swirle13 3/15/2023
你能提供输出会是什么样子吗?
0赞 unofficialdxnny 3/20/2023
我编辑了答案以包含输出图像。