TL;DR
JSON.parse()— Convert JSON string to JavaScript objectJSON.stringify()— Convert JavaScript object to JSON string- Always wrap in try-catch — Invalid JSON throws errors
- Use reviver/replacer functions for custom transformations
JSON.stringify(obj, null, 2)— Pretty print with indentation
The Two Methods You Need
JavaScript has exactly two built-in methods for working with JSON. That's it. Two methods. You'll use them constantly:
JSON.parse()— String → ObjectJSON.stringify()— Object → String
These methods are global. They're always available. They're fast. They're your new best friends.
JSON.parse() — String to Object
Got a JSON string? Need a JavaScript object? JSON.parse() is your answer.
// Simple parsing
const jsonString = '{"name": "Alice", "age": 25}';
const user = JSON.parse(jsonString);
console.log(user.name); // "Alice"
console.log(user.age); // 25
console.log(typeof user); // "object" Parsing Arrays
Arrays work exactly the same way:
const jsonArray = '[1, 2, 3, "four", true]';
const arr = JSON.parse(jsonArray);
console.log(arr); // [1, 2, 3, "four", true]
console.log(arr[3]); // "four"
console.log(Array.isArray(arr)); // true Parsing Nested Data
Complex nested structures? No problem:
const json = `{
"company": "TechCorp",
"employees": [
{"name": "Alice", "role": "Engineer"},
{"name": "Bob", "role": "Designer"}
],
"location": {
"city": "San Francisco",
"country": "USA"
}
}`;
const data = JSON.parse(json);
console.log(data.company); // "TechCorp"
console.log(data.employees[0].name); // "Alice"
console.log(data.location.city); // "San Francisco" Error Handling — Don't Skip This
Here's the thing: invalid JSON will throw an error. Not return null. Not return undefined. It will throw. Your code will crash if you don't handle it.
// This will crash your app!
const badJson = '{name: "Alice"}'; // Missing quotes around key
const data = JSON.parse(badJson); // 💥 SyntaxError! Always wrap JSON.parse() in try-catch:
function safeJsonParse(jsonString) {
try {
return JSON.parse(jsonString);
} catch (error) {
console.error('Invalid JSON:', error.message);
return null;
}
}
// Safe to use
const data = safeJsonParse('{invalid}');
if (data) {
// Work with data
} else {
// Handle the error case
} The Reviver Function — Advanced Parsing
JSON.parse() takes an optional second argument: a reviver function. This function is called for every key-value pair, letting you transform values during parsing.
const json = '{"name": "Alice", "birthDate": "1995-06-15"}';
// Parse with a reviver to convert date strings
const user = JSON.parse(json, (key, value) => {
// Check if the value looks like a date
if (key === 'birthDate') {
return new Date(value);
}
return value;
});
console.log(user.birthDate); // Date object
console.log(user.birthDate.getFullYear()); // 1995 Common Reviver Use Cases
// 1. Convert all dates automatically
function dateReviver(key, value) {
const datePattern = /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2})?/;
if (typeof value === 'string' && datePattern.test(value)) {
return new Date(value);
}
return value;
}
// 2. Convert string numbers to actual numbers
function numberReviver(key, value) {
if (typeof value === 'string' && !isNaN(value) && value.trim() !== '') {
return Number(value);
}
return value;
}
// 3. Convert keys to camelCase
function camelCaseReviver(key, value) {
if (key === '') return value; // Root object
// This transforms the key, not value
return value;
} JSON.stringify() — Object to String
Need to convert a JavaScript object to a JSON string?
Maybe for sending to an API, storing in localStorage, or logging?
JSON.stringify() has you covered.
const user = {
name: "Bob",
age: 30,
hobbies: ["coding", "gaming"]
};
const jsonString = JSON.stringify(user);
console.log(jsonString);
// '{"name":"Bob","age":30,"hobbies":["coding","gaming"]}' Pretty Printing
By default, stringify produces minified JSON. For human-readable output, use the third parameter:
const user = {
name: "Bob",
age: 30,
address: { city: "NYC", zip: "10001" }
};
// Minified (default)
JSON.stringify(user);
// '{"name":"Bob","age":30,"address":{"city":"NYC","zip":"10001"}}'
// Pretty printed with 2-space indentation
JSON.stringify(user, null, 2);
/*
{
"name": "Bob",
"age": 30,
"address": {
"city": "NYC",
"zip": "10001"
}
}
*/
// With tab indentation
JSON.stringify(user, null, '\t'); The Replacer Function — Control What's Stringified
The second parameter of stringify() can be a replacer function or array. This lets you filter or transform values during stringification.
Using an Array (Whitelist Keys)
const user = {
name: "Alice",
email: "alice@example.com",
password: "secret123", // Sensitive!
role: "admin"
};
// Only include specific keys
const safeJson = JSON.stringify(user, ['name', 'email', 'role']);
console.log(safeJson);
// '{"name":"Alice","email":"alice@example.com","role":"admin"}'
// password is excluded! Using a Function (Transform Values)
const user = {
name: "Alice",
password: "secret123",
createdAt: new Date('2024-01-15')
};
const json = JSON.stringify(user, (key, value) => {
// Hide sensitive data
if (key === 'password') {
return undefined; // Exclude from output
}
// Convert dates to ISO strings
if (value instanceof Date) {
return value.toISOString();
}
return value;
}, 2);
console.log(json);
/*
{
"name": "Alice",
"createdAt": "2024-01-15T00:00:00.000Z"
}
*/ Edge Cases and Gotchas
What Gets Lost in Stringification
Not everything survives the round trip. Here's what JSON.stringify() drops:
const obj = {
name: "Test",
func: function() { return 42; }, // Functions - DROPPED
undef: undefined, // undefined - DROPPED
sym: Symbol('id'), // Symbols - DROPPED
bigNum: BigInt(9007199254740991), // BigInt - THROWS ERROR!
nan: NaN, // Becomes null
inf: Infinity, // Becomes null
date: new Date() // Becomes string
};
console.log(JSON.stringify(obj, null, 2));
/*
{
"name": "Test",
"nan": null,
"inf": null,
"date": "2024-11-26T12:00:00.000Z"
}
*/ (key, val) => typeof val === 'bigint' ? val.toString() : val Circular References
Objects that reference themselves will throw an error:
const obj = { name: "Circular" };
obj.self = obj; // Points to itself
JSON.stringify(obj);
// 💥 TypeError: Converting circular structure to JSON
// Solution: Use a library like 'flatted' or write custom replacer Practical Examples
LocalStorage (Store Objects)
// Save to localStorage
const settings = { theme: 'dark', fontSize: 16 };
localStorage.setItem('settings', JSON.stringify(settings));
// Load from localStorage
const saved = localStorage.getItem('settings');
const loadedSettings = saved ? JSON.parse(saved) : { theme: 'light', fontSize: 14 };
console.log(loadedSettings.theme); // "dark" API Requests (Fetch)
// GET request - parse response
async function getUser(id) {
const response = await fetch(`/api/users/${id}`);
const user = await response.json(); // Built-in JSON parsing!
return user;
}
// POST request - stringify body
async function createUser(userData) {
const response = await fetch('/api/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(userData) // Stringify the body
});
return response.json();
} Deep Clone Objects
// Quick and dirty deep clone (with limitations)
const original = {
name: "Original",
nested: { value: 42 }
};
const clone = JSON.parse(JSON.stringify(original));
clone.nested.value = 100;
console.log(original.nested.value); // Still 42 - truly cloned!
// Note: This doesn't work with functions, dates, undefined, etc.
// Use structuredClone() for a proper deep clone in modern browsers Performance Tips
- Parse once — Don't parse the same JSON multiple times. Cache the result.
- Stringify carefully — Large objects with deep nesting are slow to stringify.
- Use streaming parsers for huge JSON files (e.g., JSONStream for Node.js).
- Consider Web Workers for parsing large JSON without blocking the UI.
// Bad - parsing multiple times
function getName(jsonString) {
return JSON.parse(jsonString).name;
}
function getAge(jsonString) {
return JSON.parse(jsonString).age;
}
// Good - parse once, reuse
function getUserData(jsonString) {
const user = JSON.parse(jsonString);
return {
name: user.name,
age: user.age
};
} Common Errors and Solutions
| Error | Cause | Solution |
|---|---|---|
Unexpected token | Invalid JSON syntax | Validate your JSON, check for trailing commas |
Unexpected end of JSON | Truncated or incomplete JSON | Check for complete braces/brackets |
Converting circular structure | Object references itself | Use custom replacer or library |
BigInt error | BigInt not supported | Convert to string in replacer |
Frequently Asked Questions
What's the difference between JSON.parse() and eval()?
Never use eval() for JSON! It executes arbitrary code, creating massive security vulnerabilities. JSON.parse() only parses data — it's safe.
Can JSON.parse() handle single quotes?
No. JSON requires double quotes. {'name': 'Alice'} will throw an error.
It must be {"name": "Alice"}.
How do I handle dates in JSON?
JSON doesn't have a date type. Dates are typically stored as ISO strings. Use a reviver function to convert them back to Date objects when parsing.
Is JSON.parse() synchronous?
Yes. For large JSON files, this can block the main thread. Use Web Workers or streaming parsers for huge datasets.
Keep Learning
- Common JSON Errors — Fix those cryptic error messages
- JSON Schema — Validate your JSON data
- Working with JSON APIs — Build and consume APIs
- JSON Tools — Format, validate, and convert JSON