fileview.dev

JSON, explained properly

9 min read

Written while building fileviewer.dev, a JSON viewer — which mostly means a long education in the ways real-world JSON goes wrong.

JSON is a text format for structured data with exactly six types — object, array, string, number, boolean and null — and a deliberately small grammar: no comments, no trailing commas, no dates, and no way to write Infinity or NaN.

What JSON is

JSON — JavaScript Object Notation — is a way of writing structured data as text. It was specified by Douglas Crockford in the early 2000s, standardised as ECMA-404 and RFC 8259, and has since become the default format for APIs, configuration and logs.

Its defining quality is what it leaves out. There is no schema, no versioning, no comments, no type system beyond six primitives, and no extensibility. That smallness is why every language can parse it and why two systems written decades apart can exchange data without negotiating anything.

{
  "name": "Ada Lovelace",
  "age": 36,
  "active": true,
  "nickname": null,
  "languages": ["English", "French"],
  "address": {
    "city": "London",
    "postcode": "W1J 9BW"
  }
}
A document using every type JSON has

The six types

Everything JSON can express
TypeWritten asNotes
Object{ "key": value }Keys must be double-quoted strings. Order is not guaranteed to be meaningful.
Array[1, 2, 3]Ordered. May mix types, though most consumers assume it does not.
String"text"Double quotes only. Unicode escapes as \uXXXX.
Number42, -1.5, 2e10One numeric type. No integer/float distinction, no NaN, no Infinity.
Booleantrue, falseLower case. True is not valid.
NullnullLower case. Distinct from a missing key.

Notice what is missing: no date, no binary, no decimal, no set, no reference. A date in JSON is a string by convention — usually ISO 8601 — and every consumer has to agree on that convention separately.

Six rules that catch people out

1. No trailing commas

A comma after the last element is a syntax error. This is the single most common cause of invalid JSON, because most languages that JSON resembles do allow it.

{ "a": 1, "b": 2, }   ← invalid
{ "a": 1, "b": 2 }    ← valid

2. No comments

JSON has no comment syntax, which is a frequent complaint when it is used for configuration. Crockford removed them deliberately, on the grounds that people were using them to carry parsing directives. Variants exist — JSONC, JSON5 — but a parser expecting strict JSON will reject them.

3. Duplicate keys are legal, and dangerous

The specification does not forbid a repeated key; it says the behaviour is undefined. In practice almost every parser takes the last one, silently. A configuration file with "port": 8080 near the top and "port": 3000 near the bottom is valid JSON that does not do what its author intended.

{
  "port": 8080,
  "debug": true,
  "port": 3000
}
// Valid JSON. Most parsers give you 3000. The 8080 is simply gone.

4. Numbers are doubles

JSON has one numeric type, and most parsers map it to an IEEE 754 double. That gives exactly 53 bits of integer precision. A 64-bit database identifier does not survive the round trip.

{ "id": 9007199254740993 }

// Parsed in JavaScript, Python or most other languages:
// 9007199254740992   ← the last digit changed

// The usual fix is to send large identifiers as strings:
{ "id": "9007199254740993" }

5. No NaN, no Infinity

These are not representable. JSON.stringify turns them into null without warning, which means a serialised computation result can silently become a missing value.

6. JSON is not a JavaScript object literal

They look alike, which is the problem. JavaScript allows unquoted keys, single quotes, trailing commas, comments and functions. JSON allows none of that. Code that pastes an object literal into a .json file usually produces something no parser will accept.

// Valid JavaScript, invalid JSON:
{ name: 'Ada', greet() {}, /* comment */ }

// The JSON equivalent:
{ "name": "Ada" }

Reading and writing JSON in code

const data = JSON.parse(text);        // text → value; throws on invalid input
const text = JSON.stringify(data, null, 2);  // value → text, indented by 2
JavaScript
import json

data = json.loads(text)              # text → value
text = json.dumps(data, indent=2)    # value → text
Python

In both, parsing throws on invalid input rather than returning a partial result — so a try block around the parse is not optional in anything that reads a file it did not write.

JSON Lines, and when to use it

A large JSON array has to be fully parsed before you can read the first record. JSON Lines — one complete JSON value per line, no enclosing array — can be streamed and processed a record at a time, which is why it is the usual format for logs and data exports.

{"event":"login","user":"ada","at":"2026-07-29T09:00:00Z"}
{"event":"upload","user":"ada","bytes":1024}
{"event":"logout","user":"ada"}

When JSON is the wrong choice

What to reach for instead
SituationBetter fitWhy
Configuration humans editYAML or TOMLComments, and less punctuation to get wrong
Tabular dataCSV or ParquetJSON repeats every key on every row
High-volume RPCProtobuf or MessagePackSmaller on the wire, faster to parse
Documents with markupXMLMixed content — text and elements interleaved
Exact decimals (money)Strings, or a decimal formatJSON numbers are binary floating point

Open a JSON file and look at itParsed in your browser. Nothing uploaded.

Questions

What is JSON in simple terms?

JSON is a text format for structured data. It writes values as objects (named fields in braces), arrays (ordered lists in brackets), strings, numbers, true, false and null — and nothing else. Almost every programming language can read and write it.

Can JSON have comments?

No. The specification has no comment syntax, and a strict parser rejects a document containing one. Variants like JSONC and JSON5 add them, but they are different formats — a tool expecting JSON will not accept them. Where a comment is genuinely needed, a "_comment" key is the usual workaround.

Are duplicate keys allowed in JSON?

The specification does not forbid them; it leaves the behaviour undefined. In practice nearly every parser silently keeps the last occurrence, so an earlier value disappears with no error. It is legal JSON that almost never does what its author meant.

Why does my large number change when parsed?

JSON has one numeric type, and most parsers map it to a 64-bit float, giving 53 bits of integer precision. Any integer above 9,007,199,254,740,991 may be rounded. Send large identifiers as strings.

What is the difference between JSON and a JavaScript object?

JSON is text; a JavaScript object is a value in memory. JSON is also far stricter: keys must be double-quoted, only double quotes are allowed for strings, and trailing commas, comments and functions are all invalid. Most JavaScript object literals are not valid JSON.

How do I check whether my JSON is valid?

Paste it into a validator that reports the position of the error rather than only that one exists. fileviewer.dev underlines the exact character, flags duplicate keys per object scope, and can validate against a JSON Schema — all in your browser, with nothing uploaded.