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)
Answer from Blender on Stack Overflow
Top answer
1 of 15
3096

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)
2 of 15
500

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.

🌐
Vertabelo Academy
academy.vertabelo.com › course › python-json › writing-json-files › writing-to-json-file › jsondumps-options-the-indent
How to Read and Write JSON Files in Python | Learn Python | Vertabelo Academy
A positive integer indent indent ... An indent level of 0 or negative will only insert newlines. None (the default) selects the most compact representation. Let's have a look at the result. We have saved some information in a Python object named data. Using json.dumps(), convert ...
Discussions

JSON dumps indent tab
use simplejson instead More on reddit.com
🌐 r/learnpython
2
3
October 12, 2016
python - How to custom indent json dump? - Stack Overflow
I use indent = 2, but I want the first level of indentation to be zero. For example: ... I'm really curious what's your use-case for this. ... @yedpodtrzitko I am modifying JSONs for game modding purposes, it works but it would be better if it matches the native game JSON format More on stackoverflow.com
🌐 stackoverflow.com
python - How to implement custom indentation when pretty-printing with the JSON module? - Stack Overflow
I've posted a solution that works on 2.7 and plays nicely with options such as sort_keys and does not have special case implementation for sort order and instead relies on (composition with) collections.OrderedDict. ... (Note: The code in this answer only works with json.dumps() which returns a JSON ... More on stackoverflow.com
🌐 stackoverflow.com
python - Dumping a JSON using tab indents (not spaces) - Stack Overflow
Had to change the last line to: print >> open('dev_integrated.json', 'w'), new_data Otherwise it would dump preserving the characters as is. But this is good enough. Thanks. 2017-06-29T09:16:02.433Z+00:00 ... The / 3 doesn't match the number of indented spaces, it should be 4. More on stackoverflow.com
🌐 stackoverflow.com
🌐
Python
docs.python.org › 3 › library › json.html
JSON encoder and decoder — Python 3.14.3 documentation
3 weeks ago - Changed in version 3.2: Allow strings for indent in addition to integers. Changed in version 3.4: Use (',', ': ') as default if indent is not None. Changed in version 3.6: All optional parameters are now keyword-only. json.dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)¶ ·
🌐
GeeksforGeeks
geeksforgeeks.org › python › json-dumps-in-python
json.dumps() in Python - GeeksforGeeks
import json d = {("x", "y"): 10, "a": 1} s = json.dumps(d, skipkeys=True) print(s) Output · {"a": 1} Explanation: JSON does not support tuple keys. skipkeys=True removes invalid keys automatically. Example 2: This example formats JSON output to make it more readable using indentation.
Published   January 13, 2026
🌐
DigitalOcean
digitalocean.com › community › tutorials › python-pretty-print-json
How to Pretty Print JSON in Python | DigitalOcean
September 16, 2025 - Use indent and sort_keys in json.dumps() to instantly make your JSON output readable and consistently structured.
Find elsewhere
🌐
Reddit
reddit.com › r/learnpython › json dumps indent tab
r/learnpython on Reddit: JSON dumps indent tab
October 12, 2016 -

We use Python 2.7 and I want to change the indention of JSON.dumps() to TABS instead of SPACES. When you do indent=8, it will insert 8 spaces, but I want to insert 2 tabs. I have read that this is possible in Python 3.3 by doing indent="\t\t" but we use Python 2.7.

🌐
Simon Willison
til.simonwillison.net › json › streaming-indented-json-array
Streaming output of an indented JSON array | Simon Willison’s TILs
August 29, 2023 - Here's the pattern I came up with: ... else ","), " " ) ) print("]") Here's how this works: Start by outputting a single [ - the opening square bracket for the array....
🌐
EyeHunts
tutorial.eyehunts.com › home › python json dumps indent | example
Python JSON dumps indent | Example - Tutorial - By EyeHunts
December 7, 2022 - import json data = '[{"ID":101,"Name":"John","Class":"First"},' \ '{"ID":102,"Name":"Tim","Class":"Second"}]' res = json.loads(data) # Indent = 3 print(json.dumps(res, indent=4)) ... Answer: The json module already implements some basic pretty printing with the indent parameter that specifies how many spaces to indent by: import json data = '["foo", {"bar":["baz", null, 1.0, 2]}]' res = json.loads(data) print(json.dumps(res, indent=4, sort_keys=True))
Top answer
1 of 16
32

(Note: The code in this answer only works with json.dumps() which returns a JSON formatted string, but not with json.dump() which writes directly to file-like objects. There's a modified version of it that works with both in my answer to the question Write two-dimensional list to JSON file.)

Updated

Below is a version of my original answer that has been revised several times. Unlike the original, which I posted only to show how to get the first idea in J.F.Sebastian's answer to work, and which like his, returned a non-indented string representation of the object. The latest updated version returns the Python object JSON formatted in isolation.

The keys of each coordinate dict will appear in sorted order, as per one of the OP's comments, but only if a sort_keys=True keyword argument is specified in the initial json.dumps() call driving the process, and it no longer changes the object's type to a string along the way. In other words, the actual type of the "wrapped" object is now maintained.

I think not understanding the original intent of my post resulted in number of folks downvoting it—so, primarily for that reason, I have "fixed" and improved my answer several times. The current version is a hybrid of my original answer coupled with some of the ideas @Erik Allik used in his answer, plus useful feedback from other users shown in the comments below this answer.

The following code appears to work unchanged in both Python 2.7.16 and 3.7.4.

from _ctypes import PyObj_FromPtr
import json
import re

class NoIndent(object):
    """ Value wrapper. """
    def __init__(self, value):
        self.value = value


class MyEncoder(json.JSONEncoder):
    FORMAT_SPEC = '@@{}@@'
    regex = re.compile(FORMAT_SPEC.format(r'(\d+)'))

    def __init__(self, **kwargs):
        # Save copy of any keyword argument values needed for use here.
        self.__sort_keys = kwargs.get('sort_keys', None)
        super(MyEncoder, self).__init__(**kwargs)

    def default(self, obj):
        return (self.FORMAT_SPEC.format(id(obj)) if isinstance(obj, NoIndent)
                else super(MyEncoder, self).default(obj))

    def encode(self, obj):
        format_spec = self.FORMAT_SPEC  # Local var to expedite access.
        json_repr = super(MyEncoder, self).encode(obj)  # Default JSON.

        # Replace any marked-up object ids in the JSON repr with the
        # value returned from the json.dumps() of the corresponding
        # wrapped Python object.
        for match in self.regex.finditer(json_repr):
            # see https://stackoverflow.com/a/15012814/355230
            id = int(match.group(1))
            no_indent = PyObj_FromPtr(id)
            json_obj_repr = json.dumps(no_indent.value, sort_keys=self.__sort_keys)

            # Replace the matched id string with json formatted representation
            # of the corresponding Python object.
            json_repr = json_repr.replace(
                            '"{}"'.format(format_spec.format(id)), json_obj_repr)

        return json_repr


if __name__ == '__main__':
    from string import ascii_lowercase as letters

    data_structure = {
        'layer1': {
            'layer2': {
                'layer3_1': NoIndent([{"x":1,"y":7}, {"x":0,"y":4}, {"x":5,"y":3},
                                      {"x":6,"y":9},
                                      {k: v for v, k in enumerate(letters)}]),
                'layer3_2': 'string',
                'layer3_3': NoIndent([{"x":2,"y":8,"z":3}, {"x":1,"y":5,"z":4},
                                      {"x":6,"y":9,"z":8}]),
                'layer3_4': NoIndent(list(range(20))),
            }
        }
    }

    print(json.dumps(data_structure, cls=MyEncoder, sort_keys=True, indent=2))

Output:

{
  "layer1": {
    "layer2": {
      "layer3_1": [{"x": 1, "y": 7}, {"x": 0, "y": 4}, {"x": 5, "y": 3}, {"x": 6, "y": 9}, {"a": 0, "b": 1, "c": 2, "d": 3, "e": 4, "f": 5, "g": 6, "h": 7, "i": 8, "j": 9, "k": 10, "l": 11, "m": 12, "n": 13, "o": 14, "p": 15, "q": 16, "r": 17, "s": 18, "t": 19, "u": 20, "v": 21, "w": 22, "x": 23, "y": 24, "z": 25}],
      "layer3_2": "string",
      "layer3_3": [{"x": 2, "y": 8, "z": 3}, {"x": 1, "y": 5, "z": 4}, {"x": 6, "y": 9, "z": 8}],
      "layer3_4": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
    }
  }
}
2 of 16
18

A bodge, but once you have the string from dumps(), you can perform a regular expression substitution on it, if you're sure of the format of its contents. Something along the lines of:

s = json.dumps(data_structure, indent=2)
s = re.sub('\s*{\s*"(.)": (\d+),\s*"(.)": (\d+)\s*}(,?)\s*', r'{"\1":\2,"\3":\4}\5', s)
🌐
Medium
medium.com › @blogshub4 › how-to-pretty-print-a-json-string-in-python-98a85f99ecb4
How to Pretty Print a JSON String in Python | by Blogshub | Medium
December 22, 2024 - Default Output: Without the indent parameter, the JSON is compact with no extra spaces or line breaks. Customizing Indentation: Setting indent=2 or any positive number creates a structured format.
🌐
GitHub
gist.github.com › jannismain › e96666ca4f059c3e5bc28abb711b5c92
A JSON Encoder in Python, that puts small lists on single lines. · GitHub
def readInt(file, size): return int.from_bytes(file.read(size), "little") with open("club.dat", 'rb') as datFile: datFile.read(8) size = readInt(datFile, 4) clubs = [] for i in range(size): print(f"#{i + 1}/{size} - {hex(datFile.tell())}") club = {} club['uid'] = readInt(datFile, 4) club['player'] = [(readInt(datFile, 4)) for i in range(readInt(datFile, 2))] club['mainClubId'] = readInt(datFile, 4) club['isNational'] = readInt(datFile, 2) clubs.append(club) with open("clubs.json", 'wt') as jsonFile: json.dump(clubs, jsonFile, ensure_ascii=False, indent=2)
🌐
Jsontotable
jsontotable.org › blog › python › python-pretty-print-json
Python Pretty Print JSON - Format JSON with Indentation (2025) | JSON to Table Converter
January 16, 2025 - Use json.dump() with indent to save formatted JSON files. For a complete guide, see our Python Write JSON to File tutorial. import json data = { "users": [ {"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"} ], "total": 2 } # Write pretty formatted JSON to file with open('users.json', 'w') ...
🌐
Real Python
realpython.com › python-json
Working With JSON Data in Python – Real Python
August 20, 2025 - When you call json.dumps() without indent or with None as a value, you’ll end up with one line of a compact JSON-formatted string. If you want linebreaks in your JSON string, then you can set indent to 0 or provide an empty string. Although probably less useful, you can even provide a negative number as the indentation or any other string. More commonly, you’ll provide values like 2 ...
🌐
GitHub
github.com › ijl › orjson
GitHub - ijl/orjson: Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy · GitHub
>>> import orjson >>> orjson.dumps({"a": "b", "c": {"d": True}, "e": [1, 2]}) b'{"a":"b","c":{"d":true},"e":[1,2]}' >>> orjson.dumps( {"a": "b", "c": {"d": True}, "e": [1, 2]}, option=orjson.OPT_INDENT_2 ) b'{\n "a": "b",\n "c": {\n "d": true\n },\n "e": [\n 1,\n 2\n ]\n}' If displayed, the indentation and linebreaks appear like this: ... This measures serializing the citm_catalog.json fixture, more of a worst case due to the amount of nesting and newlines, as compact (489KiB) or pretty (1.1MiB):
Starred by 8K users
Forked by 298 users
Languages   Python 52.9% | Rust 46.4% | Shell 0.7%
🌐
PYnative
pynative.com › home › python › json › python prettyprint json data
Python PrettyPrint JSON Data
May 14, 2021 - Use json.dumps() method to prettyprint JSON properly by specifying indent and separators.