JSON Formatting, Validation and JSONPath: A Practical Guide

Why JSON breaks, how to read parser errors, when to minify, and how JSONPath queries save you from scrolling through 4,000-line API responses.

If you work with APIs, you read JSON every day. Most of the time it arrives as a single line several thousand characters long, and most of the time that is fine, because a machine is reading it. The moment a human has to read it, usually because something is broken, formatting stops being cosmetic.

This guide covers what makes JSON valid, how to read the errors parsers give you, when minifying is worth it, and how JSONPath lets you query a document instead of scrolling through it. You can follow along in the JSON Formatter.

A tiny grammar, strictly enforced

JSON's whole grammar fits on a business card. A value is one of six things: an object, an array, a string, a number, true/false, or null. Objects are { "key": value } pairs separated by commas. Arrays are [ value, value ]. That is it.

Douglas Crockford described JSON in the early 2000s as a subset of JavaScript's object literal syntax, and the format was later standardized as ECMA-404 and RFC 8259. The important word is subset. Plenty of things that work in a JavaScript file are not JSON:

Works in JavaScriptValid JSON?Fix
{ name: "Ada" }NoQuote the key: { "name": "Ada" }
{ 'name': 'Ada' }NoUse double quotes
[1, 2, 3,]NoRemove the trailing comma
// commentNoRemove comments
{ "n": NaN }NoUse null or a string
{ "n": 0x1F }NoUse decimal: 31

The strictness is a feature. Because there is exactly one way to write each value, every parser in every language agrees on what a document means.

Where invalid JSON actually comes from

After years of debugging other people's payloads, I can say that invalid JSON almost always has one of a handful of causes:

  • Hand-edited config. Someone adds a line to package.json or a VS Code settings file and leaves a trailing comma. (VS Code settings are actually JSONC, JSON with comments, which is why they tolerate things other tools do not.)
  • Truncation. A log line or database column has a length limit and the object gets cut off mid-string. The parser reports "unexpected end of input".
  • Console copies. Copying an object from a browser console or a Python REPL gives you single quotes, True/None, or undefined.
  • Double encoding. A JSON string was serialized again, so you get "{\"id\":1}" instead of {"id":1}. It is valid JSON, but it is a string, not an object.
  • Invisible characters. A byte order mark or a non-breaking space at the start of a file pasted from a word processor.

When a formatter rejects your input, it is telling you that the code consuming it will reject it too. That is more useful than a tool that silently "repairs" the problem.

Reading parser errors

Modern JavaScript engines give fairly helpful errors. A message like Unexpected token } in JSON at position 42 means the parser was fine until character 42, then found a } where it expected another value. Nine times out of ten, the character just before that position is a trailing comma.

"Unexpected end of JSON input" means the document stopped before every bracket and brace was closed: look for truncation. "Unexpected token u" at position 0 usually means you tried to parse the string undefined, which happens when a variable was never set.

Beautify or minify?

Beautifying adds line breaks and indentation, two spaces per level in the RedBison formatter, so the structure is visible. It is what you want for reading, code review and committed fixtures, because a one-line change produces a one-line diff.

Minifying removes all optional whitespace. People often assume this is important for API performance, but HTTP compression (gzip or Brotli) already removes most of the cost of whitespace on the wire. Minifying is most useful where compression does not apply: environment variables, query parameters, database columns with size limits, or embedding a JSON blob in source code.

Syntax validation is not schema validation

It is worth being precise about what "valid" means. A syntax validator answers: will this parse? A schema validator answers: is this the data I expected? The document {"age": "forty"} is perfectly valid JSON. Whether age should be a number is a question for JSON Schema or a runtime validator like Zod or Pydantic in your application code.

The RedBison formatter does syntax validation with the browser's native JSON.parse, the same function your front-end code calls, so a document that passes here will parse in your app.

Querying with JSONPath

Scrolling through a 4,000-line response to find one field is a poor use of time. JSONPath, proposed by Stefan Goessner in 2007 and standardized as RFC 9535 in 2024, gives you a query language for JSON in the spirit of XPath.

Take this response:

{
  "orders": [
    { "id": 101, "status": "shipped", "total": 42.5 },
    { "id": 102, "status": "pending", "total": 12.0 },
    { "id": 103, "status": "shipped", "total": 99.9 }
  ]
}

A few useful queries:

QueryReturns
$.orders[0].id101
$.orders[*].id[101, 102, 103]
$..totalEvery total anywhere in the document
$.orders[-1:]The last order
$.orders[?(@.status == 'shipped')].id[101, 103]
$.orders[?(@.total > 40)]Orders over 40

$ is the root, . walks into an object, [*] means every element, .. searches recursively, and ?() filters with @ standing for the current item. The formatter uses the jsonpath-plus library, which supports all of these.

If you work on the command line, jq is the other tool worth learning. Its syntax is different (.orders[] | select(.status == "shipped") | .id) but the idea is the same.

A quick debugging workflow

When an API integration breaks, this is the sequence I use:

  1. Copy the raw response body from the browser network tab or curl.
  2. Paste it into the formatter. If it is invalid, the problem is on the producing side.
  3. If it is valid, beautify it and find the field your code reads with a JSONPath query.
  4. Check the type and shape: is it a string where you expected a number, or an array where you expected an object?
  5. Copy the relevant fragment into a test fixture so the bug cannot come back.

Privacy

API responses often contain personal data and tokens. The RedBison JSON Formatter parses, formats and queries entirely in your browser tab; nothing is uploaded. That is still worth double-checking for any online formatter you use, because many send your input to a server.

Related tools

Launch JSON Formatter