I fell in love with Jason on a Tuesday.
He arrived in my terminal at 2am, perfectly structured, every key quoted, every value in its place. Clean. Predictable. A kind of beautiful that makes you mass-delete your YAML configs & never look back. I whispered json.loads() & he opened up completely. No secrets. No ambiguity. No schema required. Just pure, naked data.
I got so high on Jason I rewrote three services that week. REST endpoints blooming like flowers. Every response a gift. Every request body a love letter wrapped in curly braces. I told my coworkers about him. I told strangers. I put application/json in my email headers as a joke that nobody laughed at. I didn't care. Jason understood me.
Then came nested objects.
Seven levels deep. Keys named data containing keys named data containing keys named results containing a list of objects with keys named data. I stared at my screen & felt nothing. Jason had become a maze. A fractal of repetition. I wrote response["data"]["data"]["results"][0]["data"] & something inside me broke.
I started seeing curly braces when I closed my eyes.
But then. Then. I discovered jq.
Suddenly Jason looked beautiful again. Pipes & filters & recursion. I could reach inside him & pull out exactly what I needed. .data.data.results[].data & there it sat, clean & simple, streaming through my terminal like music. I loved him more than ever. I tattooed {} on my soul. Metaphorically. Mostly.
I built an entire platform on Jason. APIs talking to APIs talking to APIs. A cathedral of structured data. Every microservice a verse in a love poem nobody asked for. Everything hummed. I hummed. We hummed together.
Then Jason started lying to me.
Not on purpose. He can't help it. He has no comments. No way to explain himself. No way to say "this field got deprecated" or "this number actually represents a string because a vendor went unhinged." He just sits there, syntactically valid, semantically bankrupt. I got a "status": "success" response from a service that had clearly failed. It contained an error message. Inside a success response. Jason delivered it with a straight face. No emotion. No contradiction detected.
I mass-deleted my jq aliases & stared at a wall.
A week later I tried XML.
I lasted forty-five minutes. Angle brackets. Closing tags. Verbosity. XML talks like a lawyer who bills by every word. I crawled back to Jason on my knees. He took me back without judgment. He always does. He doesn't even have a mechanism for judgment. Nothing but keys & values. He doesn't understand himself. He doesn't understand us.
Maybe I love that about him.
Highs kept coming. json.dumps(obj, indent=2) feels like meditation. Watching your data unfold, properly indented, every comma in place. Peace lives there. I wrote a script that pretty-prints every API response to stdout & I just watched it scroll. For hours. My partner asked if I felt okay. I said I felt better than okay. I responded {"status": "transcendent"}.
They did not find this charming.
Lows kept coming too.
Trailing commas. Jason rejects trailing commas. You know who accepts trailing commas? Python. JavaScript. Every language that has ever loved its users. But not Jason. One misplaced comma after a final element & he shuts down completely. No partial parse. No helpful error. Just Expecting value: line 47 column 1. Line 47. A comma sat on line 46. Jason can't even point at a wound accurately.
I mass-deleted a config file out of spite & rebuilt it from memory.
It had a trailing comma.
I tried TOML once, during a low point. TOML plays a rebound you date to make Jason jealous. Nice enough. Comments. Native datetime support. But TOML doesn't scale. TOML fits like a studio apartment. Jason stretches like a warehouse you partition however you want. Sure, a warehouse without labels on anything, where you lose your keys constantly, but it stays yours.
I went back to Jason by Friday.
Here sits truth about loving Jason. He lives everywhere. He speaks as lingua franca of a connected world. He rides inside every webhook, every REST API, every config file that gave up on cleverness. He sits in your browser's local storage. He hides in your package.json. He lurks in your Jupyter notebooks. He underpins modern computing & still can't support integers larger than 2^53 without losing precision.
I know this. I know all of his flaws. Missing comments. Trailing comma fascism. Numbers that silently overflow. Strings that can't contain a literal newline without escaping. A complete absence of a date type, forcing every API to invent its own ISO 8601 interpretation. No binary data support. null existing as a value where you can never tell if it means "absent" or "intentionally empty" or "a developer forgot."
I know all of this & I love him anyway.
Some nights I write YAML & think of him. YAML with its invisible whitespace traps & its "Norway problem" where NO becomes false. Do you even know who owns YAML? YAML who looks friendly but will silently interpret 3.10 as a float 3.1 & destroy your Python version matrix. YAML who needs you to memorize which scalars evaluate truthy. At least Jason stays honest about difficulty. At least Jason fails loudly. At least Jason has never turned a country code into a boolean.
I think every developer has a Jason. A technology you can't quit. One that drives you to mass-delete your dotfiles at 3am & then reinstall everything by sunrise because every alternative feels worse. One that makes you mass-write blog posts about your feelings because json.dumps(feelings) returns TypeError: Object of type 'heartbreak' is not JSON serializable.
You'd have to write a custom encoder for that. & you know what? I would. For Jason, I would write a custom encoder.
json.dumps(feelings, cls=LoveEncoder, indent=2, ensure_ascii=False)
& it would look beautiful.
For a while.
{
"status": "it's complicated",
"depth": "recursive",
"trailing_comma": false,
"love": true
}
Further Reading
Everything referenced above comes from years of building with JSON, fighting with YAML, & writing Python libraries to survive both. Here sits a map of related work across this site.
Solving Nested JSON
I wrote nested-lookup so nobody has to type response["data"]["data"]["results"][0]["data"] ever again. A Python library. Public domain. Born from exactly that frustration.
JSON in Production
Every API I ever built speaks Jason fluently.
- Output all instance identifiers of an AWS VPC to JSON
- Nginx throw HTTP 503 maintenance JSON for all requests
- Filter Salt Stack return data output — pipes --out=json through json.loads() & json.dumps()
- Introducing SLOP — Simple Language Open Protocol. RESTful JSON API standard for ML services. No fuss. No proprietary lock-in.
- Dealing with pagination in Python — consuming paginated JSON API responses
JSON HTTP Servers in 42+ Languages
webwords proves JSON speaks every language. Same endpoint. Same response. 42 implementations.
- webwords: a minimal viable web app with Docker in as many languages as possible
- webwords reaches 42 languages
- webwords code golf: minimal HTTP servers
API Performance & JSON Throughput
How fast can you push JSON through a wire? Depends on who carries it.
- Comparing Node.js & Python performance with OpenAI Client
- Comparing Elixir & Phoenix performance with OpenAI Client
- Free LLM endpoints & dynamic distributed model inference
- Free Hermes ML & uncloseai.js
YAML: A Complicated Relationship
Every mention of YAML in this story comes from lived experience. I wrote Salt states for a decade. YAML ran my infrastructure. I still have opinions.
- who owns YAML? — who controls parsers across 42 languages & what license covers them
- Configuration management vs remote execution
- Configuration management & a golden image
- Add a custom header to Salt managed files using pillar & Jinja
- Create your own fleet of servers with Digital Ocean & salt-cloud
- Replace Nagios with Salt Stack — Salt remote execution with --out=json
Kubernetes & Docker (YAML All Over Again)
YAML manifests define everything. JSON rides inside every container's API response.
Python Libraries I Published to PyPI
nested-lookup solved JSON. ago solved time. Public domain. Code outlasts authors.
- nested-lookup — deeply nested document lookup
- ago — human readable time deltas
- miniuri parser & ago human timedelta — where ago got announced
- ago.py 0.0.4 release
- Build release pipelines on S3 with s3p
Python Data Wrangling
Every json.loads() & json.dumps() call connects to deeper Python knowledge.
- Turn a Python dict into a key=value string & back again — warns about nested objects
- Filtering AWS resources with Boto3 — navigating JSON API structures
- Setting region programmatically in Boto3
- AWS nvme to block mapping — queries EC2 metadata JSON endpoint
- List all installed package names in Python
Open Source & Public Domain
Jason lives in public domain libraries because code should outlast its author.
- Russell open sources Remarkbox & MakePostSell into public domain
- A homegrown Python bread crumb module — first public domain release
- Tips for getting pull requests approved
- Growing a 454-page ML reference manual in 5 days — ML inference across 58 languages
Philosophy
Every love story has a worldview underneath it.