Academic Block

JavaScript JSON Get Certified

JSON (JavaScript Object Notation) is the standard way to exchange structured data between systems. It looks similar to a JavaScript object, but it has stricter rules. The two methods you use constantly are JSON.stringify() (object → string) and JSON.parse() (string → object).

Converting Objects to JSON

JSON.stringify() turns a JavaScript value into a JSON string. A third argument adds indentation so the output is readable.

What this code does: Converts a JavaScript object into a compact JSON string, then into a pretty-printed version with indentation.

const user = {
    name: "Michael",
    age: 28,
    active: true
};

console.log(JSON.stringify(user));
console.log(JSON.stringify(user, null, 2));

Parsing JSON Back into Objects

JSON.parse() does the reverse — it takes a JSON string and returns a real JavaScript value.

What this code does: Parses a JSON string back into a JavaScript object and reads one of its properties.

const json = '{"name":"Michael","age":28,"active":true}';

const user = JSON.parse(json);

console.log(user.name);
console.log(user.age);
console.log(typeof user);

Working with Arrays

Arrays serialize and parse exactly like objects. This is the form most APIs use when returning lists of data.

What this code does: Converts an array of objects to JSON and then parses it back so individual items can be accessed again.

const users = [
    { name: "Michael", role: "Developer" },
    { name: "David", role: "Designer" }
];

const json = JSON.stringify(users, null, 2);
console.log(json);

const parsed = JSON.parse(json);
console.log(parsed[0].name);
console.log(parsed[1].role);

What JSON.stringify() Skips

Functions, undefined, and Symbol values are not valid in JSON, so they are silently omitted.

What this code does: Shows that JSON.stringify() omits values that JSON cannot represent, such as functions, undefined, and Symbol properties.

const data = {
    name: "Michael",
    greet: function () {
        return "hi";
    },
    score: undefined,
    id: Symbol("id")
};

console.log(JSON.stringify(data));

Only name survives — the other properties are dropped.

Nested Objects and Arrays

JSON naturally supports nested structures, and both stringify and parse handle them recursively.

What this code does: Serializes a nested object containing an array, then parses the JSON back and accesses a nested array item.

const company = {
    name: "TechCorp",
    employees: [
        { name: "Michael", role: "Developer" },
        { name: "David", role: "Designer" }
    ]
};

const json = JSON.stringify(company, null, 2);
console.log(json);

const parsed = JSON.parse(json);
console.log(parsed.employees[1].name);

Filtering Keys with a replacer Function

The second argument to JSON.stringify() can be a function that runs for every key/value pair, letting you remove or transform values.

What this code does: Uses the replacer function of JSON.stringify() to remove the password property before the object is converted to JSON.

const user = {
    name: "Michael",
    age: 28,
    password: "secret123"
};

const json = JSON.stringify(user, (key, value) => {
    if (key === "password") {
        return undefined;
    }
    return value;
});

console.log(json);

Using an Array as a Whitelist

The replacer can also be an array of key names — only those keys will appear in the output.

What this code does: Uses an array as a whitelist so only the selected object properties are included in the resulting JSON string.

const user = {
    name: "Michael",
    age: 28,
    password: "secret123",
    email: "michael@example.com"
};

const json = JSON.stringify(user, ["name", "email"]);
console.log(json);

Transforming Values with a reviver Function

The second argument to JSON.parse() lets you transform values as they are parsed — commonly used to turn date strings back into real Date objects.

What this code does: Uses the reviver function of JSON.parse() to convert a JSON date string into a JavaScript Date object while parsing.

const json = '{"name":"Michael","birthDate":"2026-01-15"}';

const user = JSON.parse(json, (key, value) => {
    if (key === "birthDate") {
        return new Date(value);
    }
    return value;
});

console.log(user.birthDate instanceof Date);
console.log(user.birthDate.getFullYear());

Invalid JSON Throws a SyntaxError

JSON has stricter rules than JavaScript object literals. Parsing text that breaks those rules throws an error.

What this code does: Attempts to parse invalid JSON and catches the resulting SyntaxError so the error message can be displayed safely.

try {
    // Unquoted key and single quotes are not valid JSON
    JSON.parse("{ name: 'Michael' }");
} catch (error) {
    console.log("Error:", error.message);
}

Circular References Throw an Error

JSON.stringify() cannot handle an object that contains a reference back to itself.

What this code does: Creates a circular object reference and shows that JSON.stringify() cannot serialize circular structures and throws an error.

const obj = { name: "Michael" };
obj.self = obj;

try {
    JSON.stringify(obj);
} catch (error) {
    console.log("Error:", error.message);
}

Deep Cloning with JSON (and Its Limits)

JSON.parse(JSON.stringify(obj)) is a common deep-clone trick, but it silently loses anything JSON cannot represent.

What this code does: Demonstrates JSON-based deep cloning and also shows its limitations: the Date becomes a string and the function is not preserved.

const original = {
    name: "Michael",
    createdAt: new Date(2026, 0, 1),
    greet: function () {
        return "hi";
    }
};

const cloned = JSON.parse(JSON.stringify(original));

console.log(cloned.name);
console.log(typeof cloned.createdAt);
console.log(cloned.greet);

Prefer the modern structuredClone() function when you need an accurate deep clone.

JSON Syntax vs. JavaScript Object Syntax

Rule JSON JavaScript Object Literal
Keys must be double-quoted Yes No (quotes are optional)
Trailing commas allowed No Yes
Comments allowed No Yes
Functions allowed No Yes
undefined as a value No Yes
NaN / Infinity as numbers No Yes

Best Practices

  • Always wrap JSON.parse() in try...catch when parsing external data
  • Use a replacer to strip sensitive fields before sending or logging data
  • Use a reviver to reconstruct special types like Date objects
  • Prefer structuredClone() over the JSON round-trip for accurate deep clones
  • Never assume external JSON matches your expected shape — validate it

Quick Summary

  • JSON.stringify() converts a value to a JSON string; JSON.parse() converts it back
  • A third argument to stringify adds indentation
  • Functions, undefined, and Symbol values are silently omitted
  • A replacer filters or transforms values during stringify; a reviver transforms values during parse
  • Invalid JSON throws a SyntaxError; circular references throw a TypeError

Try It Yourself

What this code does: Combines JSON serialization, a replacer to remove a sensitive property, pretty formatting, parsing the result back, and handling invalid JSON.

const user = {
    name: "Michael",
    age: 28,
    apiKey: "sk-1234567890"
};

const json = JSON.stringify(
    user,
    (key, value) => key === "apiKey" ? undefined : value,
    2
);

console.log("Serialized:");
console.log(json);

const restored = JSON.parse(json);
console.log("Restored name:", restored.name);

try {
    JSON.parse("{ invalid json }");
} catch (error) {
    console.log("Parse error:", error.message);
}
Tip: Treat JSON as a stricter, text-only subset of JavaScript object syntax — always validate or wrap parsing in try...catch when the data comes from outside your own code.

🧪 Test Your JavaScript Code

Edit the code on the left and click “Run Code” to see the console output on the right.

📝 JavaScript Code
👁 Console Output

Click “Run Code” to see the output here.

Ctrl + Enter to run code Esc to close