JSON stands for JavaScript Object Notation. It's a lightweight, text-based format used to store and exchange data.
It's easy for humans to read and write, and easy for machines to parse and generate.
JSON is widely used when working with APIs, including when using Promises, async/await, and the Fetch API, so understanding it now will help you later.
JSON Syntax Rules
JSON follows strict formatting rules:
- Data is in name/value pairs (similar to JavaScript objects)
- Data is separated by commas
- Curly braces
{}
hold objects - Square brackets
[]
hold arrays - Strings must be in double quotes
""
(not single quotes) - No trailing commas allowed
- No comments allowed
- No functions or undefined values
Valid JSON Data Types
JSON supports these data types:
-
String: Text data enclosed in double quotes (
"
)"Hello World" "JavaScript" ""
-
Number: Both integers and floating-point numbers (no
NaN
,Infinity
, orhex
)42 3.14159 -17 0
-
Boolean: Represents
true/false
valuestrue false
-
null: Represents an empty or unknown value
null
-
Object: A collection of key-value pairs. Keys must be strings.
{ "name": "John", "age": 30, "isStudent": false }
-
Array: An ordered list of values, which can include any JSON type
[1, 2, 3, 4, 5] ["apple", "banana", "orange"] [true, false, null]
JSON vs JavaScript Objects
JSON looks like JavaScript objects but has stricter rules.
Feature | JavaScript Object | JSON |
---|---|---|
Syntax | { name: "John" } |
{ "name": "John" } |
Quotes on keys | Optional (single/double) | Required double quotes |
Strings | Single or double quotes | Double quotes only |
Functions | Allowed | Not allowed |
undefined |
Allowed | Not allowed |
Comments | Allowed | Not allowed |
Trailing commas | Allowed | Not allowed |
JSON is more strict and is meant for data only, not behavior (no functions, no comments, etc.).
JSON Methods in JavaScript
JavaScript provides two essential built-in methods for working with JSON:
JSON.stringify()
JSON.stringify()
converts a JavaScript value (object, array, number, string, etc.) into a JSON-formatted string.
Use JSON.stringify()
when:
- Sending data to a server
- Saving data in localStorage
- Debugging
Syntax:
JSON.stringify(value, replacer, space);
value
: The data you want to convertreplacer
: (optional) Filter or format the dataspace
: (optional) Add indentation (for readability)
Basic Examples:
Converting an object to JSON string:
const user = {
name: "Alice",
age: 25,
isEmployed: true,
};
const jsonString = JSON.stringify(user);
console.log(jsonString); // Output: {"name":"Alice","age":25,"isEmployed":true}
Converting an array to JSON string:
const fruits = ["apple", "banana", "orange"];
const jsonArray = JSON.stringify(fruits);
console.log(jsonArray); // Output: ["apple","banana","orange"]
Converting primitive values:
console.log(JSON.stringify(42)); // "42"
console.log(JSON.stringify("Hello")); // "\"Hello\""
console.log(JSON.stringify(true)); // "true"
console.log(JSON.stringify(null)); // "null"
Pretty Print JSON:
Add indentation for easier reading (helpful in logs, config files, etc.):
const apiResponse = {
status: "success",
data: {
users: [
{ id: 1, name: "John" },
{ id: 2, name: "Jane" },
],
},
timestamp: "2024-01-15T10:30:00Z",
};
// Pretty print with 2 spaces indentation
const prettyJson = JSON.stringify(apiResponse, null, 2);
console.log(prettyJson);
Output:
{
"status": "success",
"data": {
"users": [
{
"id": 1,
"name": "John"
},
{
"id": 2,
"name": "Jane"
}
]
},
"timestamp": "2024-01-15T10:30:00Z"
}
Using the replacer Function in JSON.stringify()
The replacer parameter in JSON.stringify(value, replacer, space)
lets you control which values get included or how they are transformed.
- It can be an array specifying keys to include.
- Or a function called for each key-value pair, allowing you to filter or modify values.
Example:
const data = {
name: "Alice",
age: null,
city: "New York",
};
const jsonString = JSON.stringify(data, (key, value) => {
if (value === null) {
return undefined; // skip this property
}
return value;
});
console.log(jsonString); // Output: {"name":"Alice","city":"New York"}
You can use the replacer function when you want to customize the JSON output, for example, to exclude sensitive data or simplify complex objects.
JSON.parse()
JSON.parse()
converts a JSON string into a JavaScript value (object, array, number, string, etc.).
This is essential when:
- Receiving data from a server (APIs)
- Reading data from localStorage, files, or databases
Syntax:
JSON.parse(text, reviver);
text
: A valid JSON stringreviver
: (optional) A function to transform the result
Basic Examples:
Parsing a JSON string to object (typical API response):
const serverResponse =
'{"status":"success","userId":123,"message":"Login successful"}';
const responseObject = JSON.parse(serverResponse);
console.log(responseObject); // Output: {status: "success", userId: 123, message: "Login successful"}
Parsing a JSON array:
const jsonArray = '["red", "green", "blue"]';
const colorsArray = JSON.parse(jsonArray);
console.log(colorsArray); // Output: ["red", "green", "blue"]
Parsing primitive values:
console.log(JSON.parse("42")); // 42
console.log(JSON.parse('"Hello"')); // "Hello"
console.log(JSON.parse("true")); // true
console.log(JSON.parse("null")); // null
Using the reviver Function in JSON.parse()
The reviver is an optional function you can pass to JSON.parse()
to customize how values are transformed during parsing.
It takes two arguments, key and value and returns the transformed value.
Example:
const json = `{
"name": "Alice",
"joined": "2025-07-15T04:00:00.000Z"
}`;
const parsed = JSON.parse(json, (key, value) => {
if (key === "joined") {
return new Date(value); // Convert ISO string to Date
}
return value;
});
console.log(parsed.joined instanceof Date); // true
console.log(parsed.joined.getFullYear()); // 2025
Here,
- The JSON string includes a date as a string ("2025-07-15T04:00:00.000Z").
- The reviver function checks each key during parsing.
- If the key is "joined", it converts the string into a real JavaScript Date object.
- Otherwise, it leaves the value as is.
You can use the reviver to sanitize, convert, or reject values as needed. It's especially useful when working with structured API responses.
Simulating API Communication
This example shows how JSON is used to send and receive data when communicating with a server.
const userData = {
username: "john_doe",
email: "john@example.com",
preferences: {
theme: "dark",
notifications: true,
},
};
// Convert to JSON for sending (this will happen automatically with fetch)
const jsonData = JSON.stringify(userData);
console.log("Data being sent to server:", jsonData);
// Simulating received data from server
const serverResponse =
'{"status":"success","userId":123,"token":"abc123xyz","message":"User created successfully"}';
// Parse the response (this will happen automatically with fetch)
const parsedResponse = JSON.parse(serverResponse);
console.log("Received from server:", parsedResponse);
// Now you can use the parsed data
if (parsedResponse.status === "success") {
console.log(`User created with ID: ${parsedResponse.userId}`);
// Store the token for future API calls
console.log(`Auth token: ${parsedResponse.token}`);
}
userData
object contains user information likeusername
,email
, andpreferences
.- Converting the object to JSON:
const jsonData = JSON.stringify(userData);
this turns the JavaScript object into a JSON string, a format suitable for sending over the network. When you usefetch()
or other APIs to send data, this conversion happens automatically.
- Logging the JSON string:
console.log("Data being sent to server:", jsonData);
you see the string version of the data, ready to be sent.
- Simulating a server response:
- The
serverResponse
variable holds a JSON string, what a server might send back after processing the request.
- The
- Parsing the JSON response back into an object:
const parsedResponse = JSON.parse(serverResponse);
converts the JSON string from the server into a JavaScript object you can use in your code.
- Logging the parsed response:
console.log("Received from server:", parsedResponse);
you see the server’s response as an object with properties likestatus
,userId
,token
, andmessage
.
- Using the parsed data:
- The code checks if the status is "success" and then accesses values from the response to:
- Show the new user's ID
- Display the authentication token
- The code checks if the status is "success" and then accesses values from the response to:
Why this matters?
- Data sent to servers must be in string format (usually JSON).
- Data received from servers is also in JSON string format and must be parsed to work with it in JavaScript.
JSON.stringify()
andJSON.parse()
are essential for this communication.- This example helps you understand the typical flow of data in web applications, preparing you for working with APIs and asynchronous JavaScript.
Error Handling with JSON
When working with JSON, errors can happen, especially when parsing data from external sources like APIs. It’s important to handle these errors so your program doesn’t crash.
Handling JSON.stringify() Errors
Sometimes JSON.stringify()
can fail, for example, if the object contains circular references.
const obj = { name: "John" };
obj.self = obj; // Circular reference causes error
function safeStringify(data) {
try {
return JSON.stringify(data);
} catch {
console.error("Error: Unable to convert object to JSON.");
return null;
}
}
const json = safeStringify(obj);
console.log(json); // null, Error: Unable to convert object to JSON.
Here,
- You create an object
obj
with a propertyname
. - Then,
obj.self = obj;
creates a circular reference (object refers to itself). - Calling
JSON.stringify(obj)
on this will throw an error because JSON cannot represent circular references. safeStringify()
wrapsJSON.stringify()
inside atry...catch
to catch this error.- If an error happens, it logs a friendly error message and returns
null
instead of crashing. - Finally, when you call
safeStringify(obj)
, it returnsnull
and prints the error.
Handling JSON.parse() Errors
Parsing JSON strings can also fail if the data is not valid JSON.
const invalidJson = '{"name": "John", age: 30}'; // Invalid JSON (unquoted key)
function safeParse(json) {
try {
return JSON.parse(json);
} catch {
console.error("Error: Invalid JSON string.");
return null;
}
}
const data = safeParse(invalidJson);
console.log(data); // null because parsing failed
const validJson = '{"name": "John", "age": 30}';
console.log(safeParse(validJson)); // { name: "John", age: 30 }
Here,
- You define a JSON string
invalidJson
that has an error: the keyage
is not quoted, which is invalid JSON syntax. safeParse()
tries to parse the string withJSON.parse()
inside atry...catch
.- When parsing fails due to invalid syntax, it catches the error, logs a message, and returns
null
. - The first call
safeParse(invalidJson)
returnsnull
because parsing failed. - Then, you test
safeParse()
with validJson, a correctly formatted JSON string. - This time, parsing succeeds and returns a JavaScript object.
What JSON Cannot Handle
JSON is great for exchanging data, but it has limitations. Some JavaScript values cannot be stored or are transformed when converting to JSON.
const complexObject = {
// These will be preserved
name: "John",
age: 30,
hobbies: ["reading", "coding"],
address: {
city: "New York",
zipCode: 10001,
},
isActive: true,
lastLogin: null,
// These will be lost or changed
greet: function () {
return "Hello!";
}, // Functions are ignored
undefinedValue: undefined, // undefined is ignored
symbolValue: Symbol("test"), // Symbols are ignored
dateValue: new Date(), // Converted to string (ISO format)
regexValue: /test/g, // Becomes empty object {}
infinityValue: Infinity, // Converted to null
nanValue: NaN, // Converted to null
};
console.log("Original object:", complexObject);
console.log("JSON string:", JSON.stringify(complexObject, null, 2));
console.log("Parsed back:", JSON.parse(JSON.stringify(complexObject)));
What Happens When You Use JSON.stringify()
?
- Preserved values:
- Strings, numbers, booleans, null
- Objects and arrays
- Lost or transformed values:
- Functions: Removed entirely (not saved)
- undefined: Removed (not saved)
- Symbols: Removed (not saved)
- Date objects: Converted to ISO date strings like "2025-07-15T10:30:00.000Z"
- Regular expressions: Become empty objects ({})
- Special numbers (Infinity, NaN): Converted to null
Why Does This Matter?
When sending or storing data as JSON, any unsupported values will not survive the conversion correctly. This can lead to missing data or unexpected results when you parse the JSON back into JavaScript.
Handling Dates Properly
JSON can’t store JavaScript Date objects directly, so you need to convert dates to strings first.
const dataWithDate = {
user: "John",
createdAt: new Date().toISOString(), // Convert to string
updatedAt: new Date().toISOString(),
};
const jsonString = JSON.stringify(dataWithDate);
const parsed = JSON.parse(jsonString);
// Convert ISO strings back to Date objects if needed
parsed.createdAt = new Date(parsed.createdAt);
parsed.updatedAt = new Date(parsed.updatedAt);
console.log("Data with dates handled correctly:", parsed);
- Store dates as ISO strings before sending or saving.
- Convert back to Date objects after parsing when you need date functionality.
This way, you keep your dates accurate and avoid issues with unsupported JSON types.
Common JSON Mistakes
When working with JSON, watch out for these common issues:
- Functions and
undefined
values are lost: JSON cannot represent functions orundefined
. These are removed during serialization (usingJSON.stringify()
). - Circular references cause errors: Objects that reference themselves cause
JSON.stringify()
to throw an error. Use custom logic or libraries like flatted to handle this. - Date objects become strings: Dates are converted to ISO strings. If you need Date objects after parsing, you must convert them back manually.
- Special numeric values become
null
: Values likeNaN
,Infinity
, and-Infinity
becomenull
when stringified. - Trailing commas or unquoted keys cause parsing errors: JSON syntax is strict. Even a trailing comma or missing quotes around keys breaks
JSON.parse()
. - Large JSON blocks can block the main thread: Parsing very large JSON strings can freeze your app temporarily. Consider chunking or asynchronous parsing.
👉 Next tutorial: Callback Hell