JSON: Syntax, Data Types & APIs
JSON (JavaScript Object Notation) is a lightweight text format for data interchange. It's language-independent, human-readable, and the dominant format for REST APIs, config files, and NoSQL databases.
Valid JSON Types
{
"string": "text value",
"number": 42,
"float": 3.14,
"negative": -7,
"scientific": 1.5e10,
"boolean_true": true,
"boolean_false": false,
"null_value": null,
"array": [1, "two", true, null, {"nested": "object"}],
"object": {
"nested": "values",
"deeper": { "a": 1 }
}
}Common Gotchas
No trailing commas — {"a":1,} is invalid (unlike JavaScript objects)
No comments — // and /* */ are not valid JSON (use JSONC for config files with comments)
Keys must be double-quoted strings — {a: 1} is invalid
Strings must use double quotes — single quotes are invalid
Numbers: no leading zeros (010 is invalid), no NaN/Infinity (not valid JSON)
No undefined — only null for missing values
Integer precision: JavaScript loses precision for integers > 2^53. Use strings for large IDs.
JSON.parse & JSON.stringify
// Basic parse/stringify
const obj = JSON.parse('{"name":"Alice","age":30}');
const json = JSON.stringify({ name: 'Alice', age: 30 });
// Pretty-print with indent
const pretty = JSON.stringify(data, null, 2);
// Replacer function — filter/transform during stringify
const filtered = JSON.stringify(user, (key, value) => {
if (key === 'password' || key === 'ssn') return undefined; // exclude sensitive
if (value instanceof Date) return value.toISOString();
return value;
}, 2);
// Array replacer — include only listed keys
JSON.stringify(user, ['name', 'email'], 2);
// Reviver function — transform during parse
const parsed = JSON.parse(jsonString, (key, value) => {
if (key === 'createdAt') return new Date(value); // string → Date
if (key === 'price') return parseFloat(value); // string → number
return value;
});
// Handle errors
try {
const data = JSON.parse(maybeInvalidJson);
} catch (err) {
console.error('Invalid JSON:', err.message);
// SyntaxError: Unexpected token ...
}Working with APIs (Fetch)
// GET request
const response = await fetch('https://api.example.com/users/1');
if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);
const user = await response.json(); // Parses JSON body
// POST with JSON body
const created = await fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`,
},
body: JSON.stringify({ name: 'Alice', email: 'alice@example.com' }),
});
const newUser = await created.json();
// Handle errors properly
async function apiRequest(url, options = {}) {
const res = await fetch(url, {
headers: { 'Content-Type': 'application/json' },
...options,
body: options.body ? JSON.stringify(options.body) : undefined,
});
if (!res.ok) {
const error = await res.json().catch(() => ({ message: res.statusText }));
throw Object.assign(new Error(error.message), { status: res.status });
}
if (res.status === 204) return null; // No content
return res.json();
}JSON in Node.js
import { readFileSync, writeFileSync } from 'fs';
import { readFile, writeFile } from 'fs/promises';
// Read JSON file synchronously
const config = JSON.parse(readFileSync('./config.json', 'utf8'));
// Read JSON file asynchronously
const data = JSON.parse(await readFile('./data.json', 'utf8'));
// Write JSON file
await writeFile('./output.json', JSON.stringify(result, null, 2) + '
');
// Deep clone via JSON (loses functions, Dates, undefined, Sets, Maps)
const clone = JSON.parse(JSON.stringify(original));
// Prefer structuredClone() in modern Node.js for proper deep cloneJSONL (Newline-Delimited JSON)
JSONL (JSON Lines) stores one JSON object per line. Used for log files, streaming APIs, and large datasets where you process records one at a time without loading everything into memory.
// Read JSONL file line by line
import { createReadStream } from 'fs';
import { createInterface } from 'readline';
const rl = createInterface({
input: createReadStream('data.jsonl'),
crlfDelay: Infinity,
});
for await (const line of rl) {
if (line.trim()) {
const record = JSON.parse(line);
await processRecord(record);
}
}
// Write JSONL
const stream = createWriteStream('output.jsonl');
for (const item of items) {
stream.write(JSON.stringify(item) + '
');
}
stream.end();Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free