JSON Guide

The data format behind APIs, config files and databases β€” syntax, data types, objects and arrays, parsing and stringifying, validation, variants and the pitfalls that break your build. Every code block has a Copy button.

Copy button on each code block  Β·  ● Beginner ● Intermediate ● Advanced

01 Introduction β€” The Data Format of the Web

JSON (JavaScript Object Notation) is a lightweight, text-based format for representing structured data. It began as a subset of JavaScript syntax, but it is now language-independent and standardised as RFC 8259 and ECMA-404. Every mainstream language β€” Python, Go, Rust, Java, C#, PHP, Ruby β€” can read and write it out of the box.

Its job is simple: move data between programs. A server serialises an object to JSON text, ships it over HTTP, and the browser parses it back into a usable object. The same format also stores configuration, logs, telemetry, and entire databases.

Where you will meet JSON

Analogy: JSON is the shipping container of data. It has one standard shape that every vehicle, crane and warehouse on the planet already knows how to handle, regardless of what is inside.

JSON is not JavaScript

A JavaScript object literal and a JSON document look similar, but JSON is stricter. Key differences:

⚠ The #1 beginner error: using JavaScript syntax in a JSON file. If your editor or API rejects the file, check for single quotes, trailing commas and comments first.
πŸ’‘ Tip: A JSON document can be a single value β€” object, array, string, number, boolean or null β€” but in practice it is almost always an object or an array at the top level.

02 Syntax & Data Types Beginner

JSON has exactly six data types. Every value in every document is one of them.

string
Double-quoted text: "hello"
number
Integer or decimal: 42, -3.14, 1e10
boolean
true or false (lowercase)
null
The absence of a value
object
Key/value pairs in { }
array
Ordered list in [ ]

A complete document

{
  "name": "Laksh",
  "age": 25,
  "isDeveloper": true,
  "nickname": null,
  "skills": ["JavaScript", "Linux", "Git"],
  "address": {
    "city": "Mangalore",
    "country": "India"
  }
}

The rules in one place

Valid vs invalid β€” spot the difference

// ❌ Invalid JSON
{
  name: 'Laksh',          // unquoted key, single quotes
  "age": 25,              // trailing comma
  "active": true
}

// βœ… Valid JSON
{
  "name": "Laksh",
  "age": 25,
  "active": true
}
πŸ’‘ Tip: Spaces and newlines outside strings are meaningless to a parser. A minified one-line document and a fully indented one are semantically identical.

03 Objects, Arrays & Nesting Beginner

Objects β€” unordered key/value pairs

An object maps names to values. The order of keys is not guaranteed by the spec β€” never rely on it when reading data.

{
  "id": 101,
  "title": "First post",
  "published": true
}

Arrays β€” ordered lists

An array holds values in a definite order. Items can be of any type, including mixed types and nested arrays.

["apple", "banana", "cherry"]
[1, 2, 3, 4, 5]
[true, null, "mixed", { "nested": true }]
[[1, 2], [3, 4]]

The shape you will see most: an array of objects

APIs almost always return a list of records. This is the canonical JSON response shape.

{
  "users": [
    { "id": 1, "name": "Ada", "role": "admin" },
    { "id": 2, "name": "Linus", "role": "developer" },
    { "id": 3, "name": "Grace", "role": "developer" }
  ],
  "total": 3
}

Empty values

{
  "object": {},
  "array": [],
  "string": "",
  "number": 0,
  "boolean": false,
  "nothing": null
}
Empty is not missing: [] means β€œa list with zero items”, while the key being absent means β€œno list was provided”. APIs often distinguish the two β€” check before assuming.
πŸ’‘ Tip: Keep nesting shallow. Three levels is usually comfortable; five levels deep makes consumers write long chains like a.b.c.d.e and break when a field is missing.

04 Strings, Numbers & Escapes Intermediate

Escape sequences

A few characters cannot appear literally inside a JSON string. Escape them with a backslash.

"quote: \"hello\""
"backslash: \\"
"newline: \n"
"tab: \t"
"carriage return: \r"
"unicode: \u00e9  (Γ©)"
"emoji: \ud83d\ude80  (πŸš€)"
⚠ Forward slashes: \/ is legal but redundant β€” plain / needs no escaping. Escaping it is harmless, just unnecessary.

Numbers have no type distinction

JSON does not separate integers from floats. Everything numeric is one number type, and the spec does not define a precision or range.

42
-3.14
1.5e10
0.0001
6.02214076e23

Invalid numbers include leading zeros (007), hexadecimal (0xFF), the special values NaN and Infinity, and a leading +.

⚠ Big integers lose precision: JavaScript numbers are IEEE-754 doubles, so integers above 2^53 - 1 (9007199254740991) cannot be represented exactly. Large database IDs and Snowflake IDs silently change when parsed. Send them as strings if precision matters.

Dates are just strings

JSON has no date type. By convention, dates travel as ISO 8601 strings, and the consumer converts them.

{
  "createdAt": "2026-10-19T09:30:00.000Z",
  "updatedAt": "2026-10-19T12:00:00Z"
}
πŸ’‘ Tip: Use new Date(json.createdAt) to parse ISO strings in JavaScript. Prefer UTC (the trailing Z) to avoid timezone drift between server and client.

05 JSON in JavaScript Intermediate

Every modern JavaScript runtime β€” browser, Node.js, Deno, Bun β€” provides exactly two methods through the global JSON object: parse and stringify.

Parsing β€” text to object

const text = '{"name":"Laksh","skills":["JS","Git"]}';
const user = JSON.parse(text);

console.log(user.name);    // "Laksh"
console.log(user.skills[0]); // "JS"

Stringifying β€” object to text

const user = {
  name: "Laksh",
  skills: ["JS", "Git"],
  active: true
};

JSON.stringify(user);
// '{"name":"Laksh","skills":["JS","Git"],"active":true}'

JSON.stringify(user, null, 2);  // pretty-print with 2 spaces

Handling parse errors

Malformed input throws a SyntaxError. Always wrap parsing of external data.

function safeParse(text) {
  try {
    return { ok: true, value: JSON.parse(text) };
  } catch (err) {
    return { ok: false, error: err.message };
  }
}

const result = safeParse('{ "broken": }');
// { ok: false, error: "Unexpected token } ..." }

Replacer and reviver

Both methods accept an optional hook. The replacer filters or transforms values while encoding; the reviver transforms values while decoding.

// Replacer: omit sensitive fields
JSON.stringify(user, (key, value) =>
  key === "password" ? undefined : value
);

// Reviver: turn ISO strings into Date objects
const data = JSON.parse(text, (key, value) =>
  key.endsWith("At") ? new Date(value) : value
);

What stringify silently drops

Deep clone: JSON.parse(JSON.stringify(obj)) is a classic clone idiom, but it loses functions, class identity, undefined, Map/Set and dates (they become strings). For modern JavaScript, prefer structuredClone(obj).
πŸ’‘ Tip: JSON.parse is safe on untrusted input β€” unlike eval, it only parses data and never executes code. Still validate the resulting shape before trusting it.

06 JSON & HTTP APIs Intermediate

JSON is the default body format for web APIs. The two headers that matter are Content-Type (what you send) and Accept (what you want back).

Reading a JSON response

const res = await fetch("https://api.example.com/users");

if (!res.ok) {
  throw new Error(`HTTP ${res.status}`);
}

const users = await res.json();
console.log(users[0].name);

Sending JSON in a request

const res = await fetch("https://api.example.com/users", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Accept": "application/json"
  },
  body: JSON.stringify({
    name: "Laksh",
    role: "developer"
  })
});

const created = await res.json();
⚠ Forgetting Content-Type: If you send a JSON string without Content-Type: application/json, many servers treat it as plain text and fail to parse the body. The header, not the string shape, is what tells the server how to read it.

Checking before parsing

res.json() throws if the body is empty or is not JSON β€” common for 204 No Content and error responses that return HTML. Check status and content type first.

const type = res.headers.get("content-type") || "";
const data = type.includes("application/json")
  ? await res.json()
  : await res.text();

Common status codes

200 OK
Request succeeded
201 Created
A new resource was made
204 No Content
Success, empty body
400 Bad Request
Invalid JSON or fields
401 Unauthorized
Missing or bad credentials
404 Not Found
Resource does not exist
422 Unprocessable
Well-formed but invalid data
500 Server Error
The server crashed
πŸ’‘ Tip: fetch does not reject on 4xx or 5xx β€” it only rejects on network failure. Always check res.ok yourself, or use a client like Axios that throws for you.

07 Validation & JSON Schema Advanced

A document can be syntactically valid JSON and still be wrong for your program. JSON Schema is the standard way to describe the expected shape and validate against it.

A small schema

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "required": ["id", "name", "email"],
  "properties": {
    "id":    { "type": "integer", "minimum": 1 },
    "name":  { "type": "string", "minLength": 1 },
    "email": { "type": "string", "format": "email" },
    "role":  { "type": "string", "enum": ["admin", "developer", "viewer"] },
    "tags":  { "type": "array", "items": { "type": "string" } }
  },
  "additionalProperties": false
}

Common keywords

type
object, array, string, number…
required
List of mandatory keys
properties
Rules per key
items
Rules for array elements
enum
Allowed values
pattern
Regex for strings
minimum / maximum
Numeric bounds
minLength / maxLength
String length bounds

Validating in code

Ajv is the most widely used validator for JavaScript and Node.js. Similar libraries exist for every language.

import Ajv from "ajv";
const ajv = new Ajv();

const validate = ajv.compile(schema);

if (!validate(data)) {
  console.error(validate.errors);
} else {
  console.log("Valid!");
}

Quick checks without code

Syntax vs schema: Syntax validation asks β€œis this valid JSON?” Schema validation asks β€œdoes this match the contract?” APIs should do both β€” reject malformed JSON with 400, and valid-but-wrong data with 422.

08 Variants & Related Formats Advanced

Strict JSON is deliberately minimal. Several extensions and sibling formats fill the gaps β€” just know which one a tool expects.

JSONL / NDJSON β€” one document per line

JSON Lines stores one complete JSON value per line. It is ideal for streaming, logs and big datasets because a consumer can process line by line without loading the whole file.

{"id":1,"event":"login","user":"ada"}
{"id":2,"event":"logout","user":"ada"}
{"id":3,"event":"login","user":"linus"}

JSON5 β€” JSON for humans

JSON5 allows comments, unquoted keys, single quotes, trailing commas and multi-line strings. It is popular in config files, but it is not standard JSON β€” APIs will reject it.

{
  // comments are allowed
  unquotedKey: 'single quotes',
  trailing: true,
}

JSONC β€” JSON with Comments

VS Code's settings.json and TypeScript's tsconfig.json accept comments and trailing commas. The file is JSONC even though its extension says .json β€” a strict validator will complain.

How the formats compare

JSON
Strict, universal, machine-first
JSON5
Relaxed syntax, configs and dev tools
JSONC
JSON + comments, VS Code / tsconfig
JSONL
One document per line, streaming
YAML
Indentation-based, comments, CI configs
TOML
Key/value config, Rust, Cargo
XML
Tags and attributes, legacy enterprise
MessagePack
Binary JSON, smaller and faster
Rule of thumb: If data crosses a network boundary, use strict JSON. If a human edits the file, YAML, TOML or JSONC may be friendlier. If it is a large event stream, use JSONL.
πŸ’‘ Tip: YAML is a superset of JSON in theory, so most JSON documents are valid YAML. The reverse is not true β€” YAML's anchors, tags and implicit typing rarely survive a round-trip to JSON unchanged.

09 Pitfalls & Best Practices Intermediate

The classic mistakes

Security and correctness

⚠ Never trust client JSON: A valid JSON document is not a safe document. Validate types, ranges, string lengths and allowed fields on the server β€” always. Syntax validation is not security.

Best practices

πŸ’‘ Tip: When debugging a parse error, the message usually includes a position. Paste the document into jq . or a JSON validator β€” it will point at the exact character, which is often a stray comma just before a closing brace.

10 Cheat Sheet

{"key": "value"}
Object with one pair
[1, 2, 3]
Array of numbers
"text"
String (double quotes)
42 / 3.14
Number (int or float)
true / false
Boolean (lowercase)
null
No value
\" \\ \n \t
String escapes
\u00e9
Unicode escape
JSON.parse(str)
Text β†’ object
JSON.stringify(obj)
Object β†’ text
stringify(obj, null, 2)
Pretty-print
structuredClone(obj)
Modern deep clone
res.json()
Parse a fetch response
Content-Type
application/json
jq . file.json
Validate and pretty-print
$schema
Point at a JSON Schema

Valid JSON in ten seconds

Remember: JSON's value is that it is boring and universal. Use the strict core for anything that crosses a network, and reach for a relaxed variant only when a human is the one editing the file.
πŸ’‘ Tip: Keep this guide bookmarked. Almost every JSON bug is one of five things: a trailing comma, a comment, a single quote, an unquoted key, or a number that lost precision.