JSON is native to JavaScript — the format was literally derived from JavaScript object syntax. Despite that, there are still important rules and patterns to understand when parsing and serializing JSON in JS and Node.js.
JSON.parse() — String to Object
JSON.parse() converts a JSON string into a JavaScript value (object, array, string, number, boolean, or null).
const jsonString = '{"name": "Alice", "age": 30, "active": true}';
const data = JSON.parse(jsonString);
console.log(data.name); // "Alice"
console.log(data.age); // 30
console.log(typeof data); // "object"
JSON.stringify() — Object to String
JSON.stringify() converts a JavaScript value into a JSON string. It accepts two optional arguments: a replacer and a space value for pretty-printing.
const user = { name: "Bob", age: 25, active: true };
// Compact
console.log(JSON.stringify(user));
// {"name":"Bob","age":25,"active":true}
// Pretty-printed (2-space indent)
console.log(JSON.stringify(user, null, 2));
// {
// "name": "Bob",
// "age": 25,
// "active": true
// }
What Gets Dropped by JSON.stringify()
Some JavaScript values cannot be represented in JSON and are silently omitted or transformed:
const obj = {
name: "Alice",
fn: () => "hello", // functions → dropped
undef: undefined, // undefined → dropped
sym: Symbol("x"), // symbols → dropped
date: new Date(), // Date → converted to ISO string
nan: NaN, // NaN → becomes null
inf: Infinity // Infinity → becomes null
};
console.log(JSON.stringify(obj, null, 2));
// { "name": "Alice", "date": "2025-07-15T...", "nan": null, "inf": null }
Parsing JSON from a fetch() Response
This is the most common real-world usage. The response.json() method automatically parses the body.
async function getUser(id) {
const response = await fetch(`https://api.example.com/users/${id}`);
if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
}
const data = await response.json(); // parse JSON body
return data;
}
const user = await getUser(1);
console.log(user.name);
Error Handling with JSON.parse()
JSON.parse() throws a SyntaxError if the input is invalid. Always wrap it in try/catch when handling external data.
function safeParseJSON(str) {
try {
return { data: JSON.parse(str), error: null };
} catch (err) {
return { data: null, error: err.message };
}
}
const { data, error } = safeParseJSON('{"broken": }');
if (error) {
console.error("Failed to parse JSON:", error);
}
Using the Reviver Function
The second argument to JSON.parse() is a reviver — a function called for each key/value pair that lets you transform values during parsing.
const json = '{"name": "Alice", "createdAt": "2025-01-15T10:00:00Z"}';
const data = JSON.parse(json, (key, value) => {
// Convert date strings back to Date objects
if (key === "createdAt") return new Date(value);
return value;
});
console.log(data.createdAt instanceof Date); // true
Deep Clone an Object with JSON
A quick (but limited) way to deep clone a plain object is to serialize then parse it. This only works for JSON-safe values.
const original = { a: 1, b: { c: [1, 2, 3] } };
const clone = JSON.parse(JSON.stringify(original));
clone.b.c.push(4);
console.log(original.b.c); // [1, 2, 3] — unaffected
For production code, prefer structuredClone() (available in modern browsers and Node.js 17+) which handles Dates, Maps, Sets, and circular references correctly.
Reading JSON Files in Node.js
// Modern Node.js (v18+) — import directly
import data from "./config.json" assert { type: "json" };
// All Node.js versions — use fs module
import { readFileSync } from "fs";
const raw = readFileSync("./data.json", "utf8");
const data = JSON.parse(raw);
// Async version
import { readFile } from "fs/promises";
const raw = await readFile("./data.json", "utf8");
const data = JSON.parse(raw);
Try Our JSON Tools
Need to validate or inspect a JSON payload before working with it in JavaScript?