Skip to content
Daily Web Lab

How to Format JSON

There are four reasonable ways to format JSON, and the one you should pick depends on where the JSON currently is. Here is each of them, plus the differences between the command-line tools that nobody mentions until a whitespace diff lands in code review.

By Umair Nazir ·

Formatting JSON, also called pretty-printing it, changes exactly one thing: the whitespace between the tokens. Newlines and indentation go in so the nesting is visible, or come out so the payload is smaller. The data is identical either way: same keys, same values, same order. That is why it is safe to reformat a file you do not fully understand.

That also means formatting is not a repair operation. Broken JSON cannot be formatted at all, because a formatter has to parse the document before it can print it back out. If your JSON will not format, what you have is a syntax error, and no amount of prettifying will fix it.

So how to format JSON comes down to one question: where is the JSON right now? Open in an editor, sitting on disk, or being produced by code you are writing. Those three cases want three different answers, and the rest of this page is each of them in turn. Nothing here needs an online formatter, though there is one on this site if you would rather just paste and go.

In your editor

For a file you already have open, the editor is the fastest route and the one you should reach for by default.

VS Code formats JSON out of the box, with no extension required. Open the file and run Format Document, bound by default to Shift+Alt+F on Windows and Linux, and Shift+Option+F on macOS. If that shortcut does nothing, it has probably been remapped or claimed by another extension; open the Command Palette with Ctrl+Shift+P (Cmd+Shift+P on macOS) and run “Format Document” by name instead.

Two settings are worth knowing. editor.tabSize controls the indent width VS Code will use, and editor.formatOnSave makes it happen every time you save, which is usually what you want for a file you are actively editing. JetBrains IDEs use Reformat Code for the same job; Sublime Text needs a package for it.

The catch with editor formatting is that it is per-file and per-person. Two developers with different tabSize values will produce different files from the same source, and the diff will be entirely whitespace. That is what .editorconfig exists to prevent.

From the terminal

For files you are not opening, output you are piping, or anything running unattended, the command line is the right tool. There are three common options and you almost certainly already have at least one.

Python, which is on nearly every machine

Python’s standard library ships a formatter, so if you have Python you already have this and there is nothing to install:

shell

python3 -m json.tool messy.json
python3 -m json.tool --indent 2 messy.json
python3 -m json.tool --sort-keys messy.json
python3 -m json.tool --compact messy.json

# reads stdin too
cat messy.json | python3 -m json.tool

It validates as it formats, so a non-zero exit status means the input was not valid JSON. The flags above were checked against Python 3.9.6. The indent options are a later addition than the module itself, so on an older interpreter run python3 -m json.tool --help to see what you actually have.

jq, if you have it

jq is a full JSON query language, and pretty-printing is what it does when you give it the identity filter . and ask for nothing else:

shell

jq . messy.json
jq --indent 4 . messy.json
jq -S . messy.json     # sort keys
jq -c . messy.json     # compact, one line

curl -s https://example.com/api | jq .

That last line is the reason jq is worth installing: piping an API response straight into it is far quicker than saving the response and opening it somewhere. It is not preinstalled on most systems, though, which makes it a poor choice for a script that has to run on machines you do not control.

Node, if the project already uses it

shell

node -e 'console.log(JSON.stringify(JSON.parse(require("fs").readFileSync("messy.json","utf8")),null,2))'

Unwieldy as a one-liner, and there is no key-sorting flag, but it needs nothing beyond Node itself and it uses the same parser your application will.

They do not agree with each other

Here is the part that catches people out, and that most write-ups skip. Format the same file with Python and with jq and you get two different files:

the same input, two formatters

$ python3 -m json.tool s.json
{
    "b": 1,          <- four spaces
    "a": [

$ jq . s.json
{
  "b": 1,            <- two spaces
  "a": [

Neither is wrong; they simply have different defaults. But if one person on a team formats with jq and another with json.tool, every commit will carry a whitespace diff across the whole file. Pick one and pass an explicit indent flag rather than relying on the default.

Default indent width, key-sorting flag, compacting flag, and failure exit code for three command-line JSON formatters
CommandDefault indentSort keysCompactExit code on bad input
python -m json.tool4 spaces--sort-keys--compact1
jq .2 spaces-S-c5
node -e (JSON.stringify)whatever you passno built-inomit the indent argument1

The exit codes matter if you are validating in CI, and they are not the same: jq exits 5 on a parse error where Python’s json.tool exits 1. Checking for a specific non-zero code will silently do the wrong thing if you later swap one for the other. Test for “not zero” instead:

shell

if ! jq . config.json > /dev/null 2>&1; then
  echo "config.json is not valid JSON"
  exit 1
fi

One thing they do agree on: both preserve the original key order unless you explicitly ask them to sort. Formatting will not quietly rearrange your document.

In your own code

When the JSON is something your program produces (a log line, a fixture, a file you are writing), format it at the point you serialise it.

javascript

// The third argument is the indent: a number of spaces, or a string.
JSON.stringify(value, null, 2)
JSON.stringify(value, null, "\t")

// Omit it entirely for the compact form.
JSON.stringify(value)

python

import json

json.dumps(obj, indent=2)
json.dumps(obj, indent=2, sort_keys=True)

# Writing straight to a file
with open("out.json", "w") as f:
    json.dump(obj, f, indent=2)

Python gives you sort_keys for free. JSON.stringify has no equivalent, because its second argument is a replacer rather than a comparator. Sorting in JavaScript means rebuilding the object with sorted keys before you stringify it.

Which way should you format JSON?

  • A file open in front of you: the editor. It is the fastest way to format JSON, and you see the result immediately.
  • An API response you are inspecting: pipe it to jq, or paste it into a browser tool.
  • A script, a git hook, or CI: python3 -m json.tool, because it is almost always already installed. Pass an explicit indent flag.
  • JSON your program writes: format at serialisation time, not afterwards.
  • Something sensitive: an editor, a local command, or a formatter that runs in your browser. Not a service that uploads it.

When it will not format at all

Every method above fails on invalid input, because every one of them parses before it prints. The error messages vary a lot in how much they tell you. Python reports a line, a column, and a character offset; jq gives a line and a column; JavaScript’s built-in parser frequently gives neither, depending on which error it hits.

the same broken input, three parsers

$ echo '{"a":1,}' | python3 -m json.tool
Expecting property name enclosed in double quotes: line 1 column 8 (char 7)

$ echo '{"a":1,}' | jq .
jq: parse error: Expected another key-value pair at line 1, column 8

Both have correctly spotted the trailing comma. JSON does not permit a comma after the final item, unlike JavaScript object literals. Trailing commas, single quotes, unquoted keys and curly quotes pasted out of a word processor account for the large majority of failures.

If the message you have is not enough to find it, the JSON Formatter reports the exact line and column with the offending character marked, and names the likely cause where it can identify one. There is a fuller walkthrough of reading parse errors on that page.

Should you commit formatted or minified JSON?

Formatted, for anything a person maintains: configuration, fixtures, translations, lockfiles you might need to read. A minified file shows up in a diff as one enormous changed line, which makes review pointless and merge conflicts painful. Formatted JSON gives you a diff you can actually read.

Minify at the point of delivery instead: when the file is served, bundled, or sent over the network. That is where the bytes matter, and it costs nothing because the transformation is lossless in both directions.

If you are already formatting on save, consider adding an .editorconfig so everyone’s editor agrees on indent width. It is a smaller commitment than a formatting hook and removes most whitespace-only diffs on its own.

Frequently asked questions

What is the fastest way to format a JSON file?

If the file is open in your editor, use the editor: in VS Code that is Format Document, bound to Shift+Alt+F on Windows and Linux or Shift+Option+F on macOS, with no extension needed. If the file is not open, python3 -m json.tool is usually quickest, because Python is already installed on nearly every machine and the module ships with it.

Why does the same JSON file look different after formatting on another machine?

Almost always because a different tool was used. Python's json.tool indents with four spaces by default while jq indents with two, so formatting one file with each produces two different files containing identical data. Editors add a third variable through their own tab-size setting. Pass an explicit indent flag rather than relying on defaults, and use an .editorconfig so editors agree.

Can I format JSON without installing anything?

Yes, in three ways. Your editor almost certainly formats JSON already. Python's json.tool is part of the standard library, so any machine with Python has it. And a browser-based formatter needs no installation at all and, if it processes locally, does not send your data anywhere.

How do I check that a JSON file is valid in a script or CI?

Run a formatter and check the exit status, since formatting requires parsing. Test for a non-zero exit rather than a specific number: jq exits 5 on a parse error while python3 -m json.tool exits 1, so a check hard-coded to one value will silently pass if the tool is ever swapped. Redirect stdout to /dev/null so the check does not print the whole file.

Does formatting JSON reorder the keys?

No, not unless you ask. Both jq and Python's json.tool preserve the original key order by default; sorting is opt-in via -S and --sort-keys respectively. Sorting is safe when you do want it, because key order carries no meaning in JSON, and it makes two versions of a document far easier to compare in a diff.

Should JSON in a git repository be formatted or minified?

Formatted, for any file a person maintains. Minified JSON appears in a diff as a single enormous changed line, which makes code review ineffective and merge conflicts hard to resolve. Minify when the file is served or bundled instead. The conversion is lossless in both directions, so nothing is lost by storing the readable version.

Ready to try it? Open the JSON Formatter — it runs entirely in your browser.

The tools here run entirely in your browser and need no cookies. We would like to use cookies only for advertising and traffic measurement, which help keep the site free. Read our privacy policy.