Notes · Sep 5, 2026

The ways a pasted JSON breaks

A document that was JSON when it left a process rarely arrives as JSON. The ways it breaks are few, and they are the same ones every time.

Fix invalid JSON — The broken webhook: dots on the bad lines, Show me lists what is wrong, Fix all rewrites those lines — the Foot counts them, ⌘Z restores every byte. · 9 s

Where broken JSON comes from

Almost never from a JSON serialiser. It comes from a language’s own object syntax — a Python repr, a JavaScript object literal pasted out of a source file, a Ruby hash — from a config dialect that allows comments and trailing commas, from a hand edit that dropped a comma, or from a log line cut at a buffer boundary. Each origin breaks the text in a characteristic way, and each way is one mechanical fix.

broken-webhook-example.json
{
  id: 'evt_1P8xQm2eZvKYlo2C',
  object: "event",
  api_version: "2026-03-20",
  created: 1745247128,
  type: 'payment_intent.succeeded',
  livemode: False,
  data: {
…

The ways, by origin

Each origin leaves its own marks, and each mark is one fix — named on its line before anything changes.

  • A Python repr — single quotes around strings, True, False and None, a trailing comma pprint leaves
  • A JavaScript object literal — unquoted keys, single quotes, trailing commas, comments
  • A config dialect — comments and trailing commas that JSON5 or JSONC allow and JSON does not
  • A hand edit — a missing comma between two values, an unclosed bracket or brace
  • A cut line — a document truncated at a buffer boundary, closed for you and said so
  • A value no serialiser writes — undefined, NaN, Infinity — read as null, and listed

What that looks like on one file

The webhook sample above — a Stripe event printed from Python and edited by hand — needs 46 fixes in 7 kinds: 31 × quote unquoted key, 7 × remove trailing comma, 3 × single → double quotes, 2 × python false → json false, 1 × insert missing comma after value, 1 × python true → json true, 1 × python none → json null. Fix all applies them, greens the lines it touched, and leaves every other byte as pasted; Undo puts the original back exactly.

What no step does: guess at content. A value that is missing stays missing and is listed as a problem with its line. Fixing syntax is mechanical; inventing data is not, and the list is where the two are kept apart.

Try it

Try it on the file that broke your afternoon.

free · no signup