| | |

JSON 03 ๐Ÿ“„ Formatting, Indentation, and White Space Rules

โฑ๏ธ Estimated read: 11 min | |

The JSON specification is explicit that whitespace is insignificant. The RFC 8259 states that insignificant whitespace is allowed before or after any of the six structural characters, and the json.org grammar says whitespace can be inserted between any pair of tokens . A proper JSON consumer will not see the difference between a minified payload and a pretty-printed one. The formatting is not a semantic concern. It is a readability concern, and the readability is for the humans who read the diffs, the configuration files, and the API responses during the debugging.

The distinction matters because the tooling treats the two concerns separately. A JSON parser does not care about the indentation, the line breaks, or the spaces between the tokens. A JSON formatter does care, and the formatter is the tool that the project runs in the CI or the pre-commit hook to enforce a consistent style. The formatter is not the parser, and the style is not the syntax. The style is the team’s decision about how the JSON should look, and the decision is the trade-off between the compactness and the readability.

Key point: Whitespace is insignificant in JSON, and a proper parser ignores it. The formatting is a readability concern, not a syntax concern. The formattersโ€”Prettier, the language-specific pretty-printersโ€”enforce a consistent style, and the style is the team’s decision. The indentation width has no standard, and the common choices are two or four spaces.


Why the formatting is a separate concern

The parser problem. The JSON parser tokenizes the text and ignores the whitespace between the tokens. The {"name":"Ada"} and the {\n "name": "Ada"\n} are the same value, and the parser produces the same object. The whitespace is not a part of the data model, and the parser does not preserve it. The distinction is the reason a minified JSON payload can be sent over the wire and a pretty-printed JSON file can be stored in the repository, and the two are semantically identical.

The diff problem. The version control system compares the lines, and a minified JSON file is a single line. A change to a single value produces a diff that shows the entire line as changed, and the reviewer cannot see what actually changed. The pretty-printed JSON file has one value per line, and the diff shows the changed line. The formatting is the mechanism that makes the code review possible, and the readability is the reason the repository stores the formatted version.

The tooling problem. The formatters are the tools that enforce the style. The Prettier is the common choice for the JavaScript ecosystem, and it formats the JSON with the json parser . The json.dump() in Python has the indent parameter, and the JSON.stringify() in JavaScript has the space parameter . The tools are the mechanism that applies the style consistently, and the consistency is the reason the style is enforced by the tooling rather than the manual editing.

The trade-off. The pretty-printed JSON is larger than the minified JSON. The extra bytes are the whitespace, and the whitespace is not the data. The size is the trade-off against the readability, and the choice depends on the context. The API response is minified because the size matters for the network transfer, and the configuration file is pretty-printed because the readability matters for the humans who edit it.


a. The indentation and the common conventions

The JSON specification does not define an indentation width. The common choices are two spaces and four spaces, and the choice is the project’s convention rather than the language’s rule . The two-space indentation is the default in Prettier, and it is the convention that the Node.js ecosystem uses. The four-space indentation is the convention that the Crockford style guide recommends, and it is common in the Java and the enterprise ecosystems.

{
  "name": "Ada",
  "age": 36
}

The two-space indentation is the Prettier default, and it is the most common in the JavaScript tooling . The tabWidth: 2 is the default, and the useTabs: false is the default. The four-space indentation is the alternative, and it is the tabWidth: 4 configuration.

{
    "name": "Ada",
    "age": 36
}

The four-space indentation is the Crockford style, and it is the common choice in the Java and the enterprise tooling. The choice is not a syntax rule, and the parser accepts either. The consistency is the concern, and the formatter is the mechanism that enforces it.

The tabs versus spaces is the second choice. The useTabs: true uses the tab character for the indentation, and the useTabs: false uses the spaces. The tabs are smaller in the file size, but the rendering depends on the editor’s tab width. The spaces are the consistent rendering, and the size is the cost. The Prettier default is the spaces, and the choice is the team’s decision.


b. The formatters and the configuration

The Prettier is the opinionated formatter that formats the JSON with the json parser. The prettier --write "**/*.json" rewrites the files, and the prettier --check "**/*.json" lists the non-compliant files without modifying them . The printWidth is the line length where the formatter wraps, and the default is 80. The tabWidth is the indentation width, and the default is 2.

// .prettierrc โ€” the JSON formatting configuration
{
  "tabWidth": 2,
  "useTabs": false,
  "printWidth": 80,
  "trailingComma": "none"
}

The trailingComma is the option that the JSON parser does not accept in the strict mode. The JSON grammar does not allow the trailing comma, and the Prettier default for the JSON parser is "none" because the trailing comma would produce an invalid JSON . The json5 parser allows the trailing comma, and the jsonc parser allows the comments and the trailing comma, and the configuration override is the mechanism that selects the parser for the specific files.

The JSON.stringify() in the JavaScript has the space parameter. The number is the number of the spaces, capped at 10, and the string is the custom indentation. The JSON.stringify(value, null, 2) produces the two-space indentation, and the JSON.stringify(value) produces the minified output.

// The two-space indentation
JSON.stringify({ name: "Ada" }, null, 2);
// '{\n  "name": "Ada"\n}'

// The four-space indentation
JSON.stringify({ name: "Ada" }, null, 4);
// '{\n    "name": "Ada"\n}'

// The minified output
JSON.stringify({ name: "Ada" });
// '{"name":"Ada"}'

The json.dump() in the Python has the indent parameter. The integer is the number of the spaces, and the None is the minified output. The indent=2 is the two-space indentation, and the indent=4 is the four-space indentation .


Complete Example Session

// ============================================
// PART 1: THE MINIFIED JSON
// ============================================

{"name":"Ada","age":36,"active":true}

// The minified output.
// The whitespace is removed.
// The parser produces the same object.

// ============================================
// PART 2: THE TWO-SPACE INDENTATION
// ============================================

{
  "name": "Ada",
  "age": 36,
  "active": true
}

// The Prettier default.
// The two-space indentation.
// The one value per line.

// ============================================
// PART 3: THE FOUR-SPACE INDENTATION
// ============================================

{
    "name": "Ada",
    "age": 36,
    "active": true
}

// The Crockford style.
// The four-space indentation.

// ============================================
// PART 4: THE PRETTIER CONFIGURATION
// ============================================

{
  "tabWidth": 2,
  "useTabs": false,
  "printWidth": 80,
  "trailingComma": "none"
}

// The tabWidth is the indentation width.
// The useTabs is the tabs vs spaces.
// The printWidth is the line length.
// The trailingComma is "none" for the strict JSON.

// ============================================
// PART 5: THE JSON.STRINGIFY SPACE
// ============================================

// The JavaScript:
const data = { name: "Ada" };
JSON.stringify(data, null, 2); // the two-space indentation
JSON.stringify(data, null, 4); // the four-space indentation
JSON.stringify(data); // the minified output

// ============================================
// PART 6: THE JSON.DUMP INDENT
// ============================================

// The Python:
import json
json.dumps(data, indent=2) // the two-space indentation
json.dumps(data, indent=4) // the four-space indentation
json.dumps(data) // the minified output

// ============================================
// PART 7: THE TRAILING COMMA
// ============================================

// The strict JSON does not allow the trailing comma.
// {"name": "Ada",} // the parse error

// The JSON5 and the JSONC allow the trailing comma.
// The Prettier json5 parser accepts it.

// ============================================
// PART 8: THE COMMENTS
// ============================================

// The strict JSON does not allow the comments.
// {"name": "Ada"} // the comment // the parse error

// The JSONC allows the comments.
// The Prettier jsonc parser accepts them.

// ============================================
// PART 9: THE PRETTIER CHECK
// ============================================

// The CI command:
// prettier --check "**/*.json"

// The output lists the non-compliant files.
// The exit code is 1 if any file is not formatted.

// ============================================
// PART 10: THE CHECKLIST
// ============================================

// [ ] The indentation width is chosen (2 or 4 spaces).
// [ ] The tabs vs spaces is chosen.
// [ ] The print width is chosen.
// [ ] The trailing comma is disabled for the strict JSON.
// [ ] The Prettier config is in the repository.
// [ ] The CI runs the prettier --check.

The ten parts covered the minified JSON, the two-space indentation, the four-space indentation, the Prettier configuration, the JSON.stringify space, the json.dump indent, the trailing comma, the comments, the Prettier check, and the checklist. The through-line is that the whitespace is insignificant, and the formatting is the readability concern.


Quick Reference

The indentation conventions

ConventionWidthSource
Prettier default2 spacesThe JavaScript ecosystem
Crockford style4 spacesThe Crockford style guide
Node.js2 spacesThe Node.js ecosystem

The Prettier JSON options

OptionDefaultPurpose
tabWidth2The indentation width
useTabsfalseThe tabs vs spaces
printWidth80The line length
trailingComma“none” (JSON)The trailing comma

The serialization options

LanguageOptionTwo-spaceMinified
JavaScriptJSON.stringifyspace: 2space: undefined
Pythonjson.dumpindent=2indent=None

The JSON parsers

ParserCommentsTrailing commaUse case
jsonNoNoThe strict JSON
json5YesYesThe human-edited config
jsoncYesYesThe VS Code config

Best Practices

โœ… Do This:

// Use the two-space indentation for the JSON
{
  "name": "Ada"
}                                                              // โœ…

// Disable the trailing comma for the strict JSON
"trailingComma": "none"                                        // โœ…

// Run the Prettier check in the CI
// prettier --check "**/*.json"                                 // โœ…

โŒ Don’t Do This:

// Use the trailing comma in the strict JSON
{ "name": "Ada", } // the parse error                           // โŒ

// Use the comments in the strict JSON
{ "name": "Ada" } // the comment // the parse error             // โŒ

// Use the inconsistent indentation
{ "name": "Ada",
    "age": 36 }                                                // โŒ

Common Pitfalls

PitfallWhy It HappensFix
The Prettier check failsThe file is not formattedRun prettier --write
The parse failsThe trailing comma or the commentUse the strict JSON or the json5 parser
The diff is noisyThe minified JSON is a single lineFormat the JSON with the Prettier
The indentation is inconsistentThe manual editingUse the formatter in the pre-commit hook

Real-World Examples

1. The minified JSON

{"name":"Ada","age":36}

2. The two-space indentation

{
  "name": "Ada"
}

3. The four-space indentation

{
    "name": "Ada"
}

4. The JavaScript stringify

JSON.stringify({ name: "Ada" }, null, 2);

5. The Python dump

json.dumps({"name": "Ada"}, indent=2)

6. The Prettier config

{ "tabWidth": 2, "useTabs": false }

7. The Prettier check

prettier --check "**/*.json"

8. The trailing comma error

{ "name": "Ada", } // the parse error

9. The comment error

{ "name": "Ada" } // the comment // the parse error

10. The JSON5 parser

{ "name": "Ada", } // the json5 parser accepts it

Visual

The Whitespace Is Insignificant

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  THE PARSER IGNORES THE WHITESPACE                           โ”‚
โ”‚                                                              โ”‚
โ”‚  '{"name":"Ada"}'                                            โ”‚
โ”‚         โ”‚                                                    โ”‚
โ”‚         โ–ผ                                                    โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                    โ”‚
โ”‚  โ”‚ The parser          โ”‚                                    โ”‚
โ”‚  โ”‚ tokenizes the text  โ”‚                                    โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                    โ”‚
โ”‚             โ”‚                                                โ”‚
โ”‚             โ–ผ                                                โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                    โ”‚
โ”‚  โ”‚ { name: "Ada" }     โ”‚  The same object                   โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                    โ”‚
โ”‚                                                              โ”‚
โ”‚  '{\n  "name": "Ada"\n}'                                     โ”‚
โ”‚         โ”‚                                                    โ”‚
โ”‚         โ–ผ                                                    โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                    โ”‚
โ”‚  โ”‚ { name: "Ada" }     โ”‚  The same object                   โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                    โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

The Formatting Is the Readability

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  THE DIFF VIEW                                               โ”‚
โ”‚                                                              โ”‚
โ”‚  Minified:                                                   โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                    โ”‚
โ”‚  โ”‚ - {"a":1,"b":2}     โ”‚  The entire line changed           โ”‚
โ”‚  โ”‚ + {"a":1,"b":3}     โ”‚                                    โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                    โ”‚
โ”‚                                                              โ”‚
โ”‚  Pretty-printed:                                             โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                    โ”‚
โ”‚  โ”‚   "a": 1,           โ”‚                                    โ”‚
โ”‚  โ”‚ - "b": 2,           โ”‚  Only the changed line             โ”‚
โ”‚  โ”‚ + "b": 3,           โ”‚                                    โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                    โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

The Indentation Width

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  THE TWO COMMON WIDTHS                                       โ”‚
โ”‚                                                              โ”‚
โ”‚  Two spaces (Prettier):                                      โ”‚
โ”‚  {                                                           โ”‚
โ”‚    "name": "Ada"                                             โ”‚
โ”‚  }                                                           โ”‚
โ”‚                                                              โ”‚
โ”‚  Four spaces (Crockford):                                    โ”‚
โ”‚  {                                                           โ”‚
โ”‚      "name": "Ada"                                           โ”‚
โ”‚  }                                                           โ”‚
โ”‚                                                              โ”‚
โ”‚  The parser accepts both.                                   โ”‚
โ”‚  The formatter enforces one.                                โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Summary

ItemValue
WhitespaceInsignificant, ignored by the parser
FormattingThe readability concern, enforced by the formatter
IndentationNo standard, 2 or 4 spaces
Prettier defaulttabWidth: 2, useTabs: false
JSON.stringifyspace parameter, 2 or 4
json.dumpindent parameter, 2 or 4
Trailing commaNot allowed in the strict JSON
CommentsNot allowed in the strict JSON

Key takeaways:

  • Whitespace is insignificant in JSON. The parser ignores the whitespace between the tokens, and a minified payload and a pretty-printed file are semantically identical . The formatting is not a syntax concern.
  • The formatting is a readability concern. The pretty-printed JSON is larger, but the diff is smaller and the review is possible. The minified JSON is smaller, but the diff is the entire line. The choice is the trade-off between the size and the readability.
  • The indentation width has no standard. The two-space indentation is the Prettier default and the common choice in the JavaScript ecosystem. The four-space indentation is the Crockford style and the common choice in the Java ecosystem .
  • The Prettier is the formatter that enforces the JSON style. The json parser is the strict one, and the json5 and jsonc parsers allow the trailing comma and the comments . The prettier --check is the CI command that lists the non-compliant files.
  • The trailing comma and the comments are not allowed in the strict JSON. The JSON.stringify does not produce them, and the strict parser rejects them. The json5 and jsonc parsers are the alternatives for the human-edited files.

Remember: The JSON whitespace is insignificant, and the parser ignores it. The formatting is the readability concern, and the formatter is the tool that enforces it. The indentation width is the team’s choice, and the two-space and the four-space are the common conventions. The strict JSON does not allow the trailing comma or the comments, and the json5 and jsonc parsers are the alternatives. The whitespace is the syntax’s non-concern, and the formatting is the team’s concern.

Was this helpful?


Stop using slow, ad-bloated tool sites! ๐Ÿคฎ

๐Ÿ”Ž Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
โœ… Finance (Mortgage, Interest, Inflation)
โœ… Tech (Base64, JSON, Dev Suite, IP)
โœ… Health (BMI, BMR, TDEE)
โœ… Productivity (Timer, Workspace, QR)

โšก๏ธ Fast & Private
๐Ÿ”’ No data leaves your device
๐Ÿ’Ž 100% Free

๐Ÿ”— Use it now: https://tools.kandz.me
๐Ÿ”– Bookmark itโ€”youโ€™ll need it later!