Skip to content
Pretty-Print with Indent
step 1/5

Reading — step 1 of 5

Read

~3 min readProduction Concerns

Pretty-Print with Indent

Compact JSON is for machines; humans get whitespace. Same serializer, different layout rules:

Compact:  {"name":"alice","tags":["a","b"]}

Pretty:
{
  "name": "alice",
  "tags": [
    "a",
    "b"
  ]
}

The layout algorithm

Pass the nesting level down the recursion; every line's indentation is " " * level:

python

That ",\n".join(items) line is doing the two things people botch by hand: the comma lands after every element except the last (JSON has no trailing commas — your own parser lessons reject them!), and the closing bracket is prefixed with pad, the parent's indent, so it lines up with the line that opened the container. Three rules complete the picture:

  • Empty containers stay inline. {} and [] never expand to an opening line plus a lonely close — zero information should cost one token, not three lines.
  • : after keys — colon, one space.
  • Scalars never break. Newlines go between structural tokens only; a string containing \n stays escaped on one line.

That last rule is the trap. Your input was parsed, so a document containing the two-character escape \n now holds a real newline character in memory. If your string writer prints it raw, the output fractures across two lines and is no longer even valid JSON. Pretty-printing changes inter-token whitespace only — in-string escaping is identical to compact mode. Reuse the same quote().

Knobs real serializers expose

Parameter (Python json.dumps)Effect
indent=2spaces per level; None = compact
separators=(",", ": ")item/key separators (the indent-mode default)
sort_keys=Truedeterministic key order
ensure_ascii=Falseemit é raw instead of \u00e9
allow_nan=Falsereject nan/inf instead of emitting invalid NaN

Determinism is why this matters beyond aesthetics: sorted keys + fixed indent means a config file diffs minimally in git, hashes identically in caches, and snapshot tests compare byte-for-byte. (For cryptographic signing, canonical compact form — RFC 8785 — is used instead; pretty is for eyes.)

Your exercise

Pretty-print with 2-space indent and sorted keys (parsing with the stdlib is allowed here; the serializer is yours). The graded shapes: {"b":2,"a":1} prints "a" before "b", each member on its own line, closing } back at column 1. Hidden test {"empty":{},"items":[]} checks the inline rule — expected output is exactly three lines with "empty": {}, and "items": [] indented two spaces. The grader-caught mistake is the parsed-newline trap: hidden input "hi\nbye" must print the single line "hi\nbye" — if your writer does not re-escape control characters, the real newline inside the parsed string splits the output in two. Deep nesting composes from the same rules: in {"x":[1,2]} the ] sits at two spaces (its opener's line indent) and the final } at zero.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…