JSON
Understand JSON syntax and how to convert between JavaScript objects and JSON text using JSON.stringify() and JSON.parse(), including JSON's limitations.
JSON (JavaScript Object Notation) is the format almost every web API uses to exchange data. It looks like a JavaScript object or array literal, but it is actually a plain text format with its own strict rules — and understanding exactly where JSON and JavaScript objects differ is essential for working with APIs, browser storage, and configuration files.
What JSON syntax looks like
JSON represents data using two structures: objects (unordered collections of key/value pairs, written with { }) and arrays (ordered lists of values, written with [ ]). Values can be strings, numbers, booleans (true/false), null, or nested objects and arrays.
JSON's rules are stricter than JavaScript object literal syntax. Every key must be a double-quoted string — single quotes and unquoted keys are not valid JSON. Trailing commas are not allowed. Values cannot be JavaScript-only things like functions, undefined, Symbols, or Dates (dates are typically represented as ISO strings instead).
• {"name": "Ada", "age": 28} — a valid JSON object • ["red", "green", "blue"] — a valid JSON array • {name: "Ada"} — INVALID JSON (unquoted key) • {"name": 'Ada'} — INVALID JSON (single quotes)
JSON.stringify() — object to text
JSON.stringify(value) converts a JavaScript value into a JSON-formatted string. This is what you do before sending data to a server in a fetch() body, or before saving an object into localStorage (which only stores strings).
JSON.stringify() silently drops any properties whose value is a function or undefined, and converts other unsupported values (like Dates) using their own rules — a Date becomes its ISO string form. It accepts optional second and third arguments for filtering keys and for indentation (useful for pretty-printing, e.g. JSON.stringify(obj, null, 2)).
JSON.parse() — text to object
JSON.parse(text) does the reverse: it takes a JSON-formatted string and converts it into a live JavaScript value (an object, array, string, number, boolean, or null).
If the string is not valid JSON — a trailing comma, single quotes, an unquoted key, or plain garbage text — JSON.parse() throws a SyntaxError. Because data from a server or from storage is not always guaranteed to be well-formed, parsing is a common place to use try/catch.
JSON's limitations
JSON cannot represent every JavaScript value. Functions and Symbols cannot be represented at all and are omitted by JSON.stringify(). undefined properties are dropped. Circular references (an object that references itself) throw an error when you try to stringify them, because JSON has no concept of pointers or shared references — every value in JSON is a plain, self-contained tree of data.
Numbers in JSON are always standard double-precision floating point — there's no separate integer type, and very large integers can lose precision. Dates have no native JSON type and are conventionally sent as ISO 8601 strings, which must be manually converted back into Date objects after parsing.
Converting between JSON and objects
JSON.stringify() produces a string with double-quoted keys, matching strict JSON rules. JSON.parse() returns a brand-new object — it is not the same reference as the original. Both functions throw on invalid input: stringify() on circular references, parse() on malformed text.
const user = { name: 'Ada', age: 28, active: true };
// Object -> JSON string
const jsonText = JSON.stringify(user);
// '{"name":"Ada","age":28,"active":true}'
// JSON string -> Object
const parsedUser = JSON.parse(jsonText);
// { name: 'Ada', age: 28, active: true }Code Examples
This shows the two functions in their simplest form. JSON.stringify() turns the settings object into a plain string suitable for storage or transmission. JSON.parse() turns that string back into a usable JavaScript object with the same shape and values. Expected result: {"theme":"dark","fontSize":16,"notifications":true} string { theme: 'dark', fontSize: 16, notifications: true } object
The third argument to JSON.stringify() (here, 2) adds indentation for readability, which is very useful when logging or saving human-readable config files. Notice that the onLoad function and the description property (which is undefined) are both silently omitted from the output — JSON has no way to represent either of them. Expected result: { "name": "SampleApp", "version": 2 } Functions and undefined values are removed entirely rather than becoming null; only values with no JSON representation at all are dropped this way.
JSON.stringify(config, null, 2) Data coming from an API response, localStorage, or user input is not guaranteed to be valid JSON. Wrapping JSON.parse() in a try/catch (here packaged into a reusable safeParse helper) prevents a single malformed string from crashing the whole application, and lets you supply a sensible fallback value instead. Expected result: { a: 1 } Invalid JSON: Expected property name or '"' in JSON at position 1 -> null Invalid JSON: Unexpected token 'o', "not json" is not valid JSON -> {} try { return JSON.parse(text); } catch (error) {... }
const settings = { theme: 'dark', fontSize: 16, notifications: true };
const text = JSON.stringify(settings);
console.log(text);
console.log(typeof text); // 'string'
const restored = JSON.parse(text);
console.log(restored);
console.log(typeof restored); // 'object'const config = {
name: 'SampleApp',
version: 2,
onLoad: function () { console.log('loaded'); },
description: undefined
};
console.log(JSON.stringify(config, null, 2));function safeParse(text, fallback = null) {
try {
return JSON.parse(text);
} catch (error) {
console.error('Invalid JSON:', error.message);
return fallback;
}
}
console.log(safeParse('{"a": 1}')); // { a: 1 }
console.log(safeParse('{a: 1}')); // Invalid JSON: ... -> null
console.log(safeParse('not json', {})); // Invalid JSON: ... -> {}Important Rules
JSON keys and string values must use double quotes — single quotes and unquoted keys are invalid.
JSON.stringify() converts a JS value to a JSON string; JSON.parse() converts a JSON string back to a JS value.
Functions, undefined, and Symbols cannot be represented in JSON and are dropped or cause errors.
Circular references cannot be stringified and will throw a TypeError.
Always wrap JSON.parse() of external or stored data in a try/catch, since malformed input throws a SyntaxError.
Where this shows up
Nearly every REST API on the web sends and receives JSON. Configuration files (package.json, tsconfig.json), browser storage, and messages sent between a web page and a server via fetch() all rely on JSON.stringify() and JSON.parse() as the universal translation layer between JavaScript's in-memory objects and portable text.
const data = JSON.parse(apiResponseText); // no error handling try { const data = JSON.parse(apiResponseText); } catch (e) { /* handle malformed response */ }
Any text that isn't guaranteed to be well-formed JSON — including data straight from a network response — can throw a SyntaxError on parse, which will crash unguarded code.
localStorage.setItem('user', user); // user is an object localStorage.setItem('user', JSON.stringify(user));
Storage APIs only accept strings. Passing an object directly silently converts it to the useless string '[object Object]' instead of preserving its data.
[Multiple Choice] What happens when you call JSON.stringify() on an object that contains a function property? A. It throws a TypeError B. The function is converted to a string of its source code C. The property is silently omitted from the resulting JSON string D. The property becomes null
C. The property is silently omitted from the resulting JSON string — JSON has no way to represent functions, so JSON.stringify() simply skips (omits) any property whose value is a function, rather than throwing or including a placeholder.
[True / False] {name: 'Ada'} (with an unquoted key) is valid JSON. A. True B. False
B. False — False. Strict JSON requires every key to be a double-quoted string. {name: 'Ada'} is valid as a JavaScript object literal, but JSON.parse() would reject it as malformed JSON.
Given an object cart = { items: ['pen', 'notebook'], total: 12.5 }, write code that converts it to a pretty-printed JSON string with 2-space indentation, logs it, then parses it back into an object and logs cart2.items[0].
const cart = { items: ['pen', 'notebook'], total: 12.5 }; const text = JSON.stringify(cart, null, 2); console.log(text); const cart2 = JSON.parse(text); console.log(cart2.items[0]); // 'pen'
Use JSON.stringify(cart, null, 2) for pretty-printing, and JSON.parse() to reverse it.