How to prettyprint a JSON file?
Question:
How do I pretty-print a JSON file in Python?
Answers:
Use the indent=
parameter of json.dump()
or json.dumps()
to specify how many spaces to indent by:
>>> 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
]
}
]
To parse a file, use json.load()
:
with open('filename.txt', 'r') as handle:
parsed = json.load(handle)
You can do this on the command line:
python3 -m json.tool some.json
(as already mentioned in the commentaries to the question, thanks to @Kai Petzke for the python3 suggestion).
Actually python is not my favourite tool as far as json processing on the command line is concerned. For simple pretty printing is ok, but if you want to manipulate the json it can become overcomplicated. You’d soon need to write a separate script-file, you could end up with maps whose keys are u"some-key" (python unicode), which makes selecting fields more difficult and doesn’t really go in the direction of pretty-printing.
You can also use jq:
jq . some.json
and you get colors as a bonus (and way easier extendability).
Addendum: There is some confusion in the comments about using jq to process large JSON files on the one hand, and having a very large jq program on the other. For pretty-printing a file consisting of a single large JSON entity, the practical limitation is RAM. For pretty-printing a 2GB file consisting of a single array of real-world data, the "maximum resident set size" required for pretty-printing was 5GB (whether using jq 1.5 or 1.6). Note also that jq can be used from within python after pip install jq
.
Pygmentize is a powerful tool for coloring the output of terminal commands.
Here is an example of using it to add syntax highlighting to the json.tool
output:
echo '{"foo": "bar"}' | python -m json.tool | pygmentize -l json
The result will look like:

In a previous Stack Overflow answer, I show in detail how to install and use pygmentize
.
Use this function and don’t sweat having to remember if your JSON is a str
or dict
again – just look at the pretty print:
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)
To be able to pretty print from the command line and be able to have control over the indentation etc. you can set up an alias similar to this:
alias jsonpp="python -c 'import sys, json; print json.dumps(json.load(sys.stdin), sort_keys=True, indent=2)'"
And then use the alias in one of these ways:
cat myfile.json | jsonpp
jsonpp < myfile.json
After reading the data with the json
standard library module, use the pprint standard library module to display the parsed data. Example:
import json
import pprint
json_data = None
with open('file_name.txt', 'r') as f:
data = f.read()
json_data = json.loads(data)
pprint.pprint(json_data)
The output will look like:
{'address': {'city': 'New York',
'postalCode': '10021-3100',
'state': 'NY',
'streetAddress': '21 2nd Street'},
'age': 27,
'children': [],
'firstName': 'John',
'isAlive': True,
'lastName': 'Smith'}
Note that this output is not valid JSON; while it shows the content of the Python data structure with nice formatting, it uses Python syntax to do so. In particular, strings are (usually) enclosed in single quotes, whereas JSON requires double quotes. To rewrite the data to a JSON file, use pprint.pformat:
pretty_print_json = pprint.pformat(json_data).replace("'", '"')
with open('file_name.json', 'w') as f:
f.write(pretty_print_json)
Here’s a simple example of pretty printing JSON to the console in a nice way in Python, without requiring the JSON to be on your computer as a local file:
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))
Use pprint: https://docs.python.org/3.6/library/pprint.html
import pprint
pprint.pprint(json)
print()
compared to 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'}
I think that’s better to parse the json before, to avoid errors:
def format_response(response):
try:
parsed = json.loads(response.text)
except JSONDecodeError:
return response.text
return json.dumps(parsed, ensure_ascii=True, indent=4)
You could try pprintjson.
Installation
$ pip3 install pprintjson
Usage
Pretty print JSON from a file using the pprintjson CLI.
$ pprintjson "./path/to/file.json"
Pretty print JSON from a stdin using the pprintjson CLI.
$ echo '{ "a": 1, "b": "string", "c": true }' | pprintjson
Pretty print JSON from a string using the pprintjson CLI.
$ pprintjson -c '{ "a": 1, "b": "string", "c": true }'
Pretty print JSON from a string with an indent of 1.
$ pprintjson -c '{ "a": 1, "b": "string", "c": true }' -i 1
Pretty print JSON from a string and save output to a file output.json.
$ pprintjson -c '{ "a": 1, "b": "string", "c": true }' -o ./output.json
Output
def saveJson(date,fileToSave):
with open(fileToSave, 'w+') as fileToSave:
json.dump(date, fileToSave, ensure_ascii=True, indent=4, sort_keys=True)
It works to display or save it to a file.
It’s far from perfect, but it does the job.
data = data.replace(',"',',n"')
you can improve it, add indenting and so on, but if you just want to be able to read a cleaner json, this is the way to go.
I had a similar requirement to dump the contents of json file for logging, something quick and easy:
print(json.dumps(json.load(open(os.path.join('<myPath>', '<myjson>'), "r")), indent = 4 ))
if you use it often then put it in a function:
def pp_json_file(path, file):
print(json.dumps(json.load(open(os.path.join(path, file), "r")), indent = 4))
TL;DR: many ways, also consider print(yaml.dump(j, sort_keys=False))
For most uses, indent should do it:
print(json.dumps(parsed, indent=2))
A Json structure is basically tree structure.
While trying to find something fancier, I came across this nice paper depicting other forms of nice trees that might be interesting: https://blog.ouseful.info/2021/07/13/exploring-the-hierarchical-structure-of-dataframes-and-csv-data/.
It has some interactive trees and even comes with some code including this collapsing tree from so:

Other samples include using plotly Here is the code example from 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()
And using treelib. On that note, This github also provides nice visualizations. Here is one example using 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()
I have, based on this, created a function to convert json to a tree:
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
Then for example:
import json
j = json.loads('{"2": 3, "4": [5, 6], "7": {"8": 9}}')
json_2_tree(j ,verbose=False,listsNodeSymbol='+' ).show()
gives:
+
├── 2
│ └── 3
├── 4
│ └── +
│ ├── 5
│ └── 6
└── 7
└── 8
└── 9
While
json_2_tree(j ,listsNodeSymbol=None, verbose=False ).show()
+
├── 2
│ └── 3
├── 4
│ ├── 5
│ └── 6
└── 7
└── 8
└── 9
And
json_2_tree(j ,compact_single_dict=True,listsNodeSymbol=None).show()
+
├── 2:3
├── 4
│ ├── 5
│ └── 6
└── 7:8:9
As you see, there are different trees one can make depending on how explicit vs. compact he wants to be.
One of my favorites, and one of the most compact ones might be using yaml:
import yaml
j = json.loads('{"2": "3", "4": ["5", "6"], "7": {"8": "9"}}')
print(yaml.dump(j, sort_keys=False))
Gives the compact and unambiguous:
'2': '3'
'4':
- '5'
- '6'
'7':
'8': '9'
How do I pretty-print a JSON file in Python?
Use the indent=
parameter of json.dump()
or json.dumps()
to specify how many spaces to indent by:
>>> 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
]
}
]
To parse a file, use json.load()
:
with open('filename.txt', 'r') as handle:
parsed = json.load(handle)
You can do this on the command line:
python3 -m json.tool some.json
(as already mentioned in the commentaries to the question, thanks to @Kai Petzke for the python3 suggestion).
Actually python is not my favourite tool as far as json processing on the command line is concerned. For simple pretty printing is ok, but if you want to manipulate the json it can become overcomplicated. You’d soon need to write a separate script-file, you could end up with maps whose keys are u"some-key" (python unicode), which makes selecting fields more difficult and doesn’t really go in the direction of pretty-printing.
You can also use jq:
jq . some.json
and you get colors as a bonus (and way easier extendability).
Addendum: There is some confusion in the comments about using jq to process large JSON files on the one hand, and having a very large jq program on the other. For pretty-printing a file consisting of a single large JSON entity, the practical limitation is RAM. For pretty-printing a 2GB file consisting of a single array of real-world data, the "maximum resident set size" required for pretty-printing was 5GB (whether using jq 1.5 or 1.6). Note also that jq can be used from within python after pip install jq
.
Pygmentize is a powerful tool for coloring the output of terminal commands.
Here is an example of using it to add syntax highlighting to the json.tool
output:
echo '{"foo": "bar"}' | python -m json.tool | pygmentize -l json
The result will look like:
In a previous Stack Overflow answer, I show in detail how to install and use pygmentize
.
Use this function and don’t sweat having to remember if your JSON is a str
or dict
again – just look at the pretty print:
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)
To be able to pretty print from the command line and be able to have control over the indentation etc. you can set up an alias similar to this:
alias jsonpp="python -c 'import sys, json; print json.dumps(json.load(sys.stdin), sort_keys=True, indent=2)'"
And then use the alias in one of these ways:
cat myfile.json | jsonpp
jsonpp < myfile.json
After reading the data with the json
standard library module, use the pprint standard library module to display the parsed data. Example:
import json
import pprint
json_data = None
with open('file_name.txt', 'r') as f:
data = f.read()
json_data = json.loads(data)
pprint.pprint(json_data)
The output will look like:
{'address': {'city': 'New York',
'postalCode': '10021-3100',
'state': 'NY',
'streetAddress': '21 2nd Street'},
'age': 27,
'children': [],
'firstName': 'John',
'isAlive': True,
'lastName': 'Smith'}
Note that this output is not valid JSON; while it shows the content of the Python data structure with nice formatting, it uses Python syntax to do so. In particular, strings are (usually) enclosed in single quotes, whereas JSON requires double quotes. To rewrite the data to a JSON file, use pprint.pformat:
pretty_print_json = pprint.pformat(json_data).replace("'", '"')
with open('file_name.json', 'w') as f:
f.write(pretty_print_json)
Here’s a simple example of pretty printing JSON to the console in a nice way in Python, without requiring the JSON to be on your computer as a local file:
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))
Use pprint: https://docs.python.org/3.6/library/pprint.html
import pprint
pprint.pprint(json)
print()
compared to 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'}
I think that’s better to parse the json before, to avoid errors:
def format_response(response):
try:
parsed = json.loads(response.text)
except JSONDecodeError:
return response.text
return json.dumps(parsed, ensure_ascii=True, indent=4)
You could try pprintjson.
Installation
$ pip3 install pprintjson
Usage
Pretty print JSON from a file using the pprintjson CLI.
$ pprintjson "./path/to/file.json"
Pretty print JSON from a stdin using the pprintjson CLI.
$ echo '{ "a": 1, "b": "string", "c": true }' | pprintjson
Pretty print JSON from a string using the pprintjson CLI.
$ pprintjson -c '{ "a": 1, "b": "string", "c": true }'
Pretty print JSON from a string with an indent of 1.
$ pprintjson -c '{ "a": 1, "b": "string", "c": true }' -i 1
Pretty print JSON from a string and save output to a file output.json.
$ pprintjson -c '{ "a": 1, "b": "string", "c": true }' -o ./output.json
Output
def saveJson(date,fileToSave):
with open(fileToSave, 'w+') as fileToSave:
json.dump(date, fileToSave, ensure_ascii=True, indent=4, sort_keys=True)
It works to display or save it to a file.
It’s far from perfect, but it does the job.
data = data.replace(',"',',n"')
you can improve it, add indenting and so on, but if you just want to be able to read a cleaner json, this is the way to go.
I had a similar requirement to dump the contents of json file for logging, something quick and easy:
print(json.dumps(json.load(open(os.path.join('<myPath>', '<myjson>'), "r")), indent = 4 ))
if you use it often then put it in a function:
def pp_json_file(path, file):
print(json.dumps(json.load(open(os.path.join(path, file), "r")), indent = 4))
TL;DR: many ways, also consider print(yaml.dump(j, sort_keys=False))
For most uses, indent should do it:
print(json.dumps(parsed, indent=2))
A Json structure is basically tree structure.
While trying to find something fancier, I came across this nice paper depicting other forms of nice trees that might be interesting: https://blog.ouseful.info/2021/07/13/exploring-the-hierarchical-structure-of-dataframes-and-csv-data/.
It has some interactive trees and even comes with some code including this collapsing tree from so:
Other samples include using plotly Here is the code example from 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()
And using treelib. On that note, This github also provides nice visualizations. Here is one example using 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()
I have, based on this, created a function to convert json to a tree:
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
Then for example:
import json
j = json.loads('{"2": 3, "4": [5, 6], "7": {"8": 9}}')
json_2_tree(j ,verbose=False,listsNodeSymbol='+' ).show()
gives:
+
├── 2
│ └── 3
├── 4
│ └── +
│ ├── 5
│ └── 6
└── 7
└── 8
└── 9
While
json_2_tree(j ,listsNodeSymbol=None, verbose=False ).show()
+
├── 2
│ └── 3
├── 4
│ ├── 5
│ └── 6
└── 7
└── 8
└── 9
And
json_2_tree(j ,compact_single_dict=True,listsNodeSymbol=None).show()
+
├── 2:3
├── 4
│ ├── 5
│ └── 6
└── 7:8:9
As you see, there are different trees one can make depending on how explicit vs. compact he wants to be.
One of my favorites, and one of the most compact ones might be using yaml:
import yaml
j = json.loads('{"2": "3", "4": ["5", "6"], "7": {"8": "9"}}')
print(yaml.dump(j, sort_keys=False))
Gives the compact and unambiguous:
'2': '3'
'4':
- '5'
- '6'
'7':
'8': '9'