JSON cheat sheet

A scannable JSON reference: 31 short snippets across 12 topics, each linking back to the lesson it came from.

At a glance

TopicWhat it covers
Syntax and typesThe complete JSON grammar, the values that look valid but are not, and how JSON compares to a JavaScript object literallesson
parse, stringify, revivers and replacersConvert between text and data safely, transform values during parsing, and know exactly which JavaScript values cannotlesson
JSON in HTTP APIsResponse envelopes, a stable error shape, timestamps as strings, and the error messages you will meet most oftenlesson
Reading and inspecting JSON from the command lineSeveral tools accept a relaxed dialect for configuration. They are not JSON, and a parser that complies with thelesson
Designing a JSON payloadNaming, null versus omitted, envelopes, pagination and error contracts - the decisions that are cheap now and expensivelesson
Dates, numbers and precisionRepresent time unambiguously, keep money out of floating point, and know exactly when a JSON number stops being thelesson
Validating with JSON SchemaDescribe the payload you accept, validate it at the boundary, compose schemas with references and conditionals, andlesson
JSON Lines, streaming and large documentsUse NDJSON for event and log data, parse it line by line, and process files too large to load without running out oflesson
JSON in databases and storageQuery and index JSON columns in PostgreSQL and MySQL, work with nested documents in MongoDB, and recognise whenlesson
Security when parsing untrusted JSONPrototype pollution, size and depth limits, schema validation as an actual control, and keeping JSON safe where it islesson
When to use something elseYAML, TOML, CSV, MessagePack and Protobuf each win somewhere JSON does not - and each has a cost worth naming beforelesson
Testing and mocking JSON APIsBuild fixtures and factories, generate data from a schema, mock at the network boundary, and stop snapshots from makinglesson

Quick snippets

Syntax and types

The whole grammar

{
  "id": 42,
  "name": "Ada",
  "active": true,
  "score": 9.5,
  "tags": ["math", "code"],
  "address": { "city": "London", "postcode": "N1 9GU" },
  "manager": null
}

Rules that trip people up

{
  "line": "first\nsecond",
  "path": "C:\\Users\\ada",
  "quote": "she said \"hello\"",
  "char": "\u00e9"
}

JSON versus a JavaScript object literal

// the same data written as a JavaScript object literal
const cfg = {
  name: 'app',        // comments and single quotes are fine here
  retries: undefined, // valid JavaScript, invalid JSON
  tags: ['a', 'b',],  // trailing comma allowed
};

// converting between the two representations
const text = JSON.stringify(cfg);   // {"name":"app","tags":["a","b"]}
const back = JSON.parse(text);      // plain data, no functions, no undefined

Full lesson: Syntax and types →

parse, stringify, revivers and replacers

Revivers: transforming during parse

const iso = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/;

const dto = JSON.parse(text, (key, value) => {
  if (typeof value === 'string' && iso.test(value)) return new Date(value);
  if (key === 'total') return Number(value) || 0;
  if (key === '__proto__') return undefined;   // drop prototype-polluting keys
  return value;
});

dto.createdAt instanceof Date;   // true

Full lesson: parse, stringify, revivers and replacers →

JSON in HTTP APIs

Choosing a response shape

{
  "data": [
    { "id": 1, "title": "First", "dueAt": "2026-09-20T09:00:00Z" },
    { "id": 2, "title": "Second", "dueAt": null }
  ],
  "meta": { "page": 1, "perPage": 20, "total": 137 }
}

A stable error shape

{
  "error": {
    "code": "validation_failed",
    "message": "The request body is not valid.",
    "details": [
      { "field": "email", "issue": "must contain @" }
    ]
  }
}

Practical pitfalls

const res = await fetch('/api/tasks', { headers: { Accept: 'application/json' } });

// a 200 does not mean the body is JSON
const type = res.headers.get('content-type') || '';
if (!type.includes('json')) {
  throw new Error('expected JSON, got ' + type);
}
const payload = await res.json();

// dates always arrive as strings and must be converted by the client
const dueAt = payload.data[0].dueAt ? new Date(payload.data[0].dueAt) : null;

Full lesson: JSON in HTTP APIs →

Reading and inspecting JSON from the command line

Fetch and format

# what did the server actually send?
curl -sI https://api.example.com/orders | grep -i content-type

# and what does the error look like when the request is wrong?
curl -s https://api.example.com/orders/999 | jq .

JSONC and JSON5 config files

// a JSONC file: valid for the editor, invalid for JSON.parse
{
  // the compiler options that matter for this package
  "compilerOptions": {
    "strict": true,
    "noEmit": true,
  },
}

// reading it in code needs a tolerant parser
import { parse } from "jsonc-parser";
const config = parse(await readFile("tsconfig.json", "utf8"));

JSONC and JSON5 config files

# strip comments and trailing commas before sending it anywhere
npx strip-json-comments tsconfig.json | jq . > /tmp/clean.json

# JSON5 from the command line
npx json5 -s config.json5

Full lesson: Reading and inspecting JSON from the command line →

Designing a JSON payload

Names, nulls and shape

{
  "id": "ord_9f2c",
  "customer_id": "cus_1042",
  "line_items": [
    { "sku": "A-1", "quantity": 2, "unit_price_minor": 1999 }
  ],
  "total_minor": 3998,
  "currency": "GBP",
  "placed_at": "2026-09-18T11:04:22Z",
  "cancelled_at": null,
  "coupon": null
}

Envelopes and pagination

{
  "data": [
    { "id": "ord_9f2c" },
    { "id": "ord_9f30" }
  ],
  "meta": {
    "request_id": "req_7c1a",
    "next_cursor": "eyJpZCI6Im9yZF85ZjMwIn0",
    "has_more": true
  }
}

Envelopes and pagination

{
  "error": {
    "code": "VALIDATION_FAILED",
    "message": "Quantity must be at least 1.",
    "details": [
      { "field": "line_items[0].quantity", "issue": "minimum", "limit": 1 }
    ],
    "request_id": "req_7c1a"
  }
}

Full lesson: Designing a JSON payload →

Dates, numbers and precision

Time as a string

{
  "placed_at": "2026-09-18T11:04:22Z",
  "placed_at_offset": "2026-09-18T12:04:22+01:00",
  "delivery_date": "2026-09-21",
  "trial_ends_epoch_ms": 1790000000000
}

Time as a string

// the two mistakes that show up in production
JSON.parse('{"d":"2026-09-18 11:04:22"}').d      // no zone: parsed as local time
new Date("2026-09-18").toISOString()              // "2026-09-18T00:00:00.000Z" in UTC,
                                                  // but the previous day in a negative offset

// a date-only value is not an instant - keep it a string
const deliveryDate = "2026-09-21";
Number.isFinite(Date.parse(deliveryDate));        // true, but the instant is zone-dependent

Numbers that survive the trip

Number.MAX_SAFE_INTEGER;      // 9007199254740991
Number.MAX_SAFE_INTEGER + 1;  // 9007199254740992
Number.MAX_SAFE_INTEGER + 2;  // 9007199254740992 - the same number

// a 64-bit identifier, as it round-trips through JSON
const id = 9007199254740993n;
JSON.parse('{"id":9007199254740993}').id;      // 9007199254740992 - silently wrong

// floats are binary, so decimals are approximate
0.1 + 0.2;                                     // 0.30000000000000004
JSON.parse('{"total":10.1}').total * 3;        // 30.299999999999997

Full lesson: Dates, numbers and precision →

Validating with JSON Schema

One schema, several outputs

# TypeScript types from the schema
npx json-schema-to-typescript schemas/order.json -o src/types/order.d.ts

# Python models
datamodel-codegen --input schemas/order.json --output models/order.py

# generate a valid example, useful for fixtures and docs
npx json-schema-faker schemas/order.json > fixtures/order.json

# documentation, if your toolchain renders it
npx @adobe/jsonschema2md -d schemas -o docs/schemas

One schema, several outputs

test("rejects an order with no line items", () => {
  expect(validate({ id: "ord_1", total_minor: 0, currency: "GBP", line_items: [] })).toBe(false);
});

test("rejects an unknown property", () => {
  expect(validate({ id: "ord_1", total_minor: 0, currency: "GBP", extra: 1 })).toBe(false);
});

Full lesson: Validating with JSON Schema →

JSON Lines, streaming and large documents

One object per line

{"ts":"2026-09-18T11:00:00Z","level":"info","msg":"started","pid":412}
{"ts":"2026-09-18T11:00:01Z","level":"warn","msg":"retry","attempt":1}
{"ts":"2026-09-18T11:00:04Z","level":"info","msg":"ready","port":3000}

Files that do not fit in memory

// this loads the whole file, then doubles it while parsing
const all = JSON.parse(await readFile("big.json", "utf8"));   // 2 GB file, 4 GB+ of RAM

// line-oriented processing stays flat
const rl = createInterface({ input: createReadStream("big.ndjson") });
let count = 0;
for await (const line of rl) {
  if (!line.trim()) continue;
  if (JSON.parse(line).level === "error") count++;
}
console.log(count);

Files that do not fit in memory

# inspect a large NDJSON file without loading it all
head -c 500 big.ndjson
wc -l big.ndjson

# filter and count with jq, streaming
jq -c 'select(.level == "error")' big.ndjson | wc -l

# sample the first 20 records
head -20 big.ndjson | jq -s .

Full lesson: JSON Lines, streaming and large documents →

JSON in databases and storage

When to normalise instead

-- a schema in practice, expressed as a constraint
ALTER TABLE events ADD CONSTRAINT payload_shape CHECK (
  jsonb_typeof(payload) = 'object'
  AND payload ? 'level'
  AND jsonb_typeof(payload -> 'level') = 'string'
);

Full lesson: JSON in databases and storage →

Security when parsing untrusted JSON

Size, depth and cost

# what does your endpoint do with a 10 MB nested body?
python - <<'PY' > /tmp/deep.json
depth = 20000
print('{"a":' * depth + '1' + '}' * depth)
PY

curl -s -o /dev/null -w '%{http_code} %{size_upload}\n' \
  -X POST http://localhost:3000/api/events \
  -H 'Content-Type: application/json' \
  --data-binary @/tmp/deep.json

JSON embedded in HTML and logs

// a payload written into a page must not be able to close the containing block
function safeForInlineJson(value) {
  return JSON.stringify(value)
    .replace(/</g, "\\u003c")
    .replace(/>/g, "\\u003e")
    .replace(/&/g, "\\u0026")
    .replace(/\u2028/g, "\\u2028")
    .replace(/\u2029/g, "\\u2029");
}

// escaping the opening angle bracket is what stops a string value
// from terminating the surrounding HTML element

JSON embedded in HTML and logs

// redaction before anything is written to a log
const SECRET = /^(password|token|authorization|card_number|cvv)$/i;

function redact(value) {
  if (Array.isArray(value)) return value.map(redact);
  if (value && typeof value === "object") {
    return Object.fromEntries(
      Object.entries(value).map(([k, v]) => [k, SECRET.test(k) ? "[redacted]" : redact(v)])
    );
  }
  return value;
}

Full lesson: Security when parsing untrusted JSON →

When to use something else

Configuration: YAML and TOML

# YAML: comments, anchors, and significant indentation
defaults: &defaults
  retries: 3
  timeout_seconds: 30

services:
  api:
    <<: *defaults
    port: 8080
    hosts:
      - api.example.com
      - api.internal

Configuration: YAML and TOML

# TOML: explicit, typed, and unambiguous about nesting
[service]
name = "api"
port = 8080

[service.limits]
retries = 3
timeout_seconds = 30
enabled = true
released = 2026-09-18          # a real date type, not a string

Tabular data: CSV

id,email,plan,created_at
1042,[email protected],annual,2026-01-04
1043,[email protected],monthly,2026-02-11

Full lesson: When to use something else →

Testing and mocking JSON APIs

Fixtures and factories

// fixtures/order.json - a real recorded response, trimmed
{
  "data": {
    "id": "ord_9f2c",
    "total_minor": 3998,
    "currency": "GBP",
    "status": "placed",
    "placed_at": "2026-09-18T11:04:22Z",
    "line_items": [{ "sku": "A-1", "quantity": 2 }]
  },
  "meta": { "request_id": "req_7c1a" }
}

Generated data and schema checks

# random-but-valid data from the schema
npx json-schema-faker schemas/order.json --count 5 > fixtures/orders.random.json

# a property-style check on the parser itself
npx fast-check --example

Mocking at the boundary

// a snapshot that fails for the right reasons
expect(anOrder().data).toMatchObject({
  currency: "GBP",
  status: "placed",
  line_items: [{ sku: "A-1", quantity: 2 }],
});

Full lesson: Testing and mocking JSON APIs →

FAQ

Is this JSON cheat sheet free to use?
Yes. No sign-up and no tracking: the page is static, every example is on the page itself, and you can print it or save it as a one-page reference.
Where do the examples come from?
Every snippet is taken from the 12 lessons of the JSON course on this site, and each section links back to the lesson it was pulled from.
How do I go deeper than a cheat sheet?
Open the full JSON course — it carries the worked explanations, the edge cases and the exercises behind every line here.

HTML CSS JavaScript TypeScript HTML DOM AJAX

Last refreshed 2026-09-27.