esc
Anthology / Yagnipedia / JSON

JSON

The Data Format That Won by Not Trying
Technology · First observed 2001 (Douglas Crockford, who insists he "discovered" rather than invented it) · Severity: Foundational

JSON (JavaScript Object Notation) is a data interchange format that won the format wars by having no features — no schemas, no namespaces, no processing instructions, no comments, no trailing commas — and being exactly sufficient for everything the industry needed, which turns out to be: objects, arrays, strings, numbers, booleans, and null.

JSON was “discovered” by Douglas Crockford in 2001, who deliberately uses the word “discovered” rather than “invented” because JSON is not an invention. JSON is a subset of JavaScript object literal syntax that already existed. Crockford wrote it down, gave it a name, put it on a website, and the world adopted it — not because it was marketed, not because it was standardized by committee, but because a developer could look at a JSON document and understand it without reading a specification.

{
  "name": "The Lizard",
  "speaks": false,
  "blinks": true,
  "principles": ["simplicity", "directness", "one binary"]
}

This is the entire sales pitch. No angle brackets. No attributes vs. elements debate. No closing tags. No CDATA sections. No entity references. Just braces, brackets, colons, and commas. A format so simple that hand-writing a parser is a weekend project and a rite of passage.

The XML Replacement

JSON replaced XML as the default data interchange format on the web, not through superior technology but through inferior complexity. XML could do everything JSON could do, plus schemas, namespaces, transformations, validation, and the ability to embed processing instructions. JSON could do none of these things. JSON won.

This is the Boring Technology principle applied to data formats: the format with fewer features wins because the features it lacks are features nobody wanted. Nobody wanted to write a schema for an API response. Nobody wanted namespaces in their configuration file. Nobody wanted to close every tag they opened. They wanted to send an object from one program to another, and JSON let them do it with the minimum possible ceremony.

The transition was not instant. SOAP held on for years. Enterprise architects defended XML with the fervour of those whose careers depended on its complexity. But the API economy — the millions of REST endpoints that appeared between 2005 and 2015 — chose JSON overwhelmingly, because a developer could read a JSON response in a browser’s network tab and understand it immediately. Reading an XML SOAP response required a decoder ring, an XSD schema, and the spiritual fortitude of a medieval monk.

The Hand-Rolled Parser

The lifelog’s most vivid JSON episode is documented in The Wallet We Gave, where a hand-rolled partial JSON parser was discovered in the codebase:

func extractJSONField(json, field string) string {
    idx := strings.Index(json, pattern)

The parser existed because streaming AI responses arrive as partial JSON — incomplete fragments that must be parsed incrementally. The Squirrel’s instinct was to build a StreamingJSONParserWithIncrementalFieldExtraction. The actual solution was a library called streaming-json-go that completed partial JSON into valid JSON, which the standard library then parsed.

“We built a JSON parser.”
“Every developer builds a JSON parser exactly once.”
riclib and Claude, The Wallet We Gave

180 lines of hand-rolled parser. Deleted. Replaced with a library call. The Squirrel wanted architecture. The Lizard wanted json.Unmarshal.

The IAM Dialect

JSON’s most perverse application is AWS IAM policies — JSON documents that define access control with a precision that approaches natural language and a readability that approaches none.

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": "s3:GetObject",
    "Resource": "arn:aws:s3:::my-bucket/*",
    "Condition": {
      "StringEquals": {
        "s3:ExistingObjectTag/classification": "public"
      }
    }
  }]
}

This is a simple policy. Production policies are not simple. Production policies have multiple statements, each with multiple actions, each with multiple resources, each with conditions that reference other policies. The result is a JSON document that functions as a programming language — with conditionals, variables, and boolean logic — expressed in a format that was designed for data interchange between web services.

IAM policy JSON is what happens when a data format becomes a governance language. The format is not the problem. The problem is that the governance is complex, and JSON makes the complexity visible, which is either its greatest strength (you can read it) or its greatest weakness (you have to read it).

The NDJSON Frontier

The lifelog’s encounter with Azure Blob Storage in The Thread Before the Name revealed another JSON dialect: NDJSON (Newline-Delimited JSON). Each line is a complete JSON object. No wrapping array. No commas between objects. Just objects, separated by newlines, streamed into files that can be processed line by line without loading the entire document into memory.

{"operationName":"tokenLogin","time":"2025-12-10T03:09:39Z"}
{"operationName":"tokenLogin","time":"2025-12-10T03:12:15Z"}

NDJSON is JSON’s most boring variant and therefore its most useful. It is JSON that has accepted its role as a log format. No pretence of structure beyond the line. No schema. No validation. Just objects, falling into files, waiting to be queried by someone who knows what jq is.

The Missing Features

JSON has no comments. This is deliberate. Crockford excluded comments because he observed that people used comments to embed parsing directives, which defeated the purpose of a simple interchange format. The result is that every JSON configuration file in existence — package.json, tsconfig.json, launch.json — must express configuration without the ability to explain why a particular value was chosen.

JSON has no trailing commas. Adding an item to the end of an array requires modifying two lines: the new item and the comma on the previous item. This produces noisy diffs. Every developer knows this. The specification does not care.

JSON has no date type. Dates are strings. Which string format? ISO 8601, usually. Or Unix timestamps. Or the American format. Or the European format. The format is unstated because JSON does not have a date type. The format is convention, which means the format is “whatever the previous developer chose” and the debugging session is “why is this date in epoch milliseconds.”

These missing features are not oversights. They are the reason JSON won. Every feature that XML has and JSON lacks is a feature that requires a decision, a configuration, and a potential source of bugs. JSON has no decisions. JSON has six types. JSON is done.

Measured Characteristics

See Also