JavaScriptIntermediate

JavaScript JSON: parse, stringify and Working with JSON Data

Learn JSON in JavaScript: JSON.parse, JSON.stringify, replacers, revivers, errors, localStorage and API data, with real examples and common mistakes.

All JavaScript lessons

What you will learn

Every time you log in to a website, load a list of products, or save a setting, data travels between your browser and a server. That data is sent as text, and the most popular format for it is JSON. In this lesson you will learn what JSON is, how it differs from a JavaScript object, how to convert in both directions with JSON.stringify and JSON.parse, how to handle errors, how to customise the result with replacers and revivers, and how JSON is used in real projects such as localStorage and APIs.

Want to check or beautify a piece of JSON while you learn? Use the free JSON Formatter tool. Paste your text and it will format it and show you if there is a mistake.

What is JSON?

JSON stands for JavaScript Object Notation. It is a text format for storing and sending data. It looks like a JavaScript object, but it is only a string that follows strict rules.

{
  "name": "Riya",
  "age": 22,
  "isStudent": true,
  "skills": ["HTML", "CSS", "JS"],
  "address": { "city": "Delhi" },
  "nickname": null
}

Why is JSON so popular?

  • It is easy to read for humans.
  • It is small and simple for computers.
  • Every language (JavaScript, Python, Java, PHP…) can read and write it.

The rules of JSON

JSON is stricter than a JavaScript object:

Rule JavaScript object Valid JSON
Keys name or "name" Must be in double quotes: "name"
Text values 'hi', "hi" or `hi` Only double quotes: "hi"
Trailing comma Allowed Not allowed
Comments Allowed Not allowed
Functions, undefined, Symbol Allowed Not allowed

The allowed JSON value types are: string, number, boolean, null, array and object. Nothing else.

Remember: a JavaScript object lives inside your program. JSON is text that you send, save or receive. To move between the two, you convert.

The two methods

Method Direction Example
JSON.stringify(value) JavaScript value to JSON text object to string
JSON.parse(text) JSON text to JavaScript value string to object

Easy way to remember: stringify makes a string. parse reads (parses) the string back into data.

JSON.stringify: object to text

const user = { name: "Riya", age: 22, skills: ["HTML", "CSS"] };

const text = JSON.stringify(user);

console.log(text);          // {"name":"Riya","age":22,"skills":["HTML","CSS"]}
console.log(typeof text);   // "string"

It works with arrays, text, numbers and booleans too:

console.log(JSON.stringify([1, 2, 3]));     // "[1,2,3]"
console.log(JSON.stringify("hello"));       // "\"hello\"" (quotes are part of the text)
console.log(JSON.stringify(42));            // "42"
console.log(JSON.stringify(true));          // "true"
console.log(JSON.stringify(null));          // "null"

Pretty printing with the third argument

The third argument adds spaces so the output is easy to read:

const user = { name: "Riya", address: { city: "Delhi" } };

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

Output:

{
  "name": "Riya",
  "address": {
    "city": "Delhi"
  }
}

The null in the middle is the “replacer” (you will learn it below). The 2 means “indent with 2 spaces”. You can also pass a text such as "\t" to indent with tabs.

What stringify does with special values

Not everything can become JSON. Here is what happens:

const data = {
  name: "Riya",
  greet() { return "hi"; },      // function: skipped
  secret: undefined,             // undefined: skipped
  id: Symbol("id"),              // symbol: skipped
  score: NaN,                    // NaN becomes null
  limit: Infinity,               // Infinity becomes null
  joined: new Date(Date.UTC(2026, 9, 2))   // Date becomes an ISO text
};

console.log(JSON.stringify(data));
// {"name":"Riya","score":null,"limit":null,"joined":"2026-10-02T00:00:00.000Z"}

Inside arrays, those same values become null (to keep the positions):

console.log(JSON.stringify([1, undefined, function () {}, 4]));
// [1,null,null,4]

More things to know:

  • A Map or a Set becomes {} (empty). Convert them first with Object.fromEntries(map) or [...set].
  • A BigInt throws a TypeError.
  • A circular reference (an object that points back to itself) throws a TypeError.
const a = { name: "A" };
a.self = a;

try {
  JSON.stringify(a);
} catch (error) {
  console.log(error.name);   // "TypeError" (circular structure)
}

Choosing properties: the replacer

The second argument lets you filter or change what goes into the JSON.

As an array: list the property names you want to keep.

const user = { name: "Riya", age: 22, password: "secret123" };

console.log(JSON.stringify(user, ["name", "age"]));
// {"name":"Riya","age":22}

As a function: it runs for every key and value. Return the value to keep, or undefined to remove it.

const user = { name: "Riya", password: "secret123", age: 22 };

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

console.log(safe);   // {"name":"Riya","age":22}

Custom output with toJSON

If an object has a toJSON method, stringify uses its result. This is how Date becomes text.

const product = {
  title: "Pen",
  price: 10,
  internalCode: "X-99",
  toJSON() {
    return { title: this.title, price: this.price };   // hide internalCode
  }
};

console.log(JSON.stringify(product));   // {"title":"Pen","price":10}

JSON.parse: text to object

const text = '{"name":"Riya","age":22,"skills":["HTML","CSS"]}';

const user = JSON.parse(text);

console.log(user.name);        // "Riya"
console.log(user.skills[1]);   // "CSS"
console.log(typeof user);      // "object"

It can also parse simple values:

console.log(JSON.parse("42"));          // 42
console.log(JSON.parse("true"));        // true
console.log(JSON.parse("null"));        // null
console.log(JSON.parse("[1, 2, 3]"));   // [1, 2, 3]
console.log(JSON.parse('"hello"'));     // "hello"

Note the quotes: the JSON text for the word hello is "hello" with double quotes inside.

Invalid JSON throws an error

If the text is not valid JSON, JSON.parse throws a SyntaxError. Here are the usual reasons:

// All of these throw SyntaxError:
// JSON.parse("{ name: 'Riya' }");         // keys and text need double quotes
// JSON.parse("{'name': 'Riya'}");         // single quotes not allowed
// JSON.parse('{"name": "Riya",}');        // trailing comma
// JSON.parse("");                         // empty text
// JSON.parse(undefined);                  // becomes the text "undefined"
// JSON.parse('{"a": undefined}');         // undefined is not valid JSON

So always protect parsing of data you do not control with try...catch:

function safeParse(text, fallback = null) {
  try {
    return JSON.parse(text);
  } catch (error) {
    console.log("Invalid JSON:", error.name);
    return fallback;
  }
}

console.log(safeParse('{"ok": true}'));        // { ok: true }
console.log(safeParse("{ broken json", {}));   // {}

Tip: if you cannot find the mistake in a big JSON text, paste it in the JSON Formatter. It points to the problem.

Changing values while parsing: the reviver

JSON.parse has an optional second argument, a reviver function. It runs for each key and value, and lets you transform the result.

JSON has no date type, so dates come back as text. A reviver can turn them into real Date objects:

const text = '{"title":"Post","published":"2026-10-02T00:00:00.000Z"}';

const post = JSON.parse(text, (key, value) => {
  if (key === "published") return new Date(value);
  return value;
});

console.log(post.published instanceof Date);        // true
console.log(post.published.getUTCFullYear());       // 2026

The round trip

Saving and loading is just stringify then parse:

const original = { name: "Riya", scores: [90, 85] };

const text = JSON.stringify(original);   // save this
const restored = JSON.parse(text);       // load it back

console.log(restored);                  // { name: "Riya", scores: [90, 85] }
console.log(restored === original);     // false (it is a new object)

What does not survive the round trip: functions, undefined, Symbol, Date objects (they come back as text), Map and Set, and class methods. Keep that in mind.

Real-life use cases

1. Saving data in localStorage

localStorage can store only text, so JSON is the perfect partner:

const settings = { theme: "dark", fontSize: 18 };

localStorage.setItem("settings", JSON.stringify(settings));

const saved = JSON.parse(localStorage.getItem("settings"));
console.log(saved.theme);   // "dark"

A safe version that handles missing or broken data:

function loadSettings() {
  try {
    const raw = localStorage.getItem("settings");
    return raw ? JSON.parse(raw) : { theme: "light", fontSize: 16 };
  } catch {
    return { theme: "light", fontSize: 16 };
  }
}

console.log(loadSettings());

2. Reading data from an API

Most APIs reply in JSON. fetch has a helper response.json() that does the parsing for you (you will learn fetch and async/await later in the course):

// You will understand this fully in the Fetch API lesson
async function loadUser() {
  const response = await fetch("https://jsonplaceholder.typicode.com/users/1");
  const user = await response.json();   // JSON text to object
  console.log(user.name);
}

loadUser();

To send data, do the reverse with stringify:

// fetch("/api/users", {
//   method: "POST",
//   headers: { "Content-Type": "application/json" },
//   body: JSON.stringify({ name: "Riya", age: 22 })
// });

3. A quick deep copy (for plain data only)

const original = { name: "Riya", address: { city: "Delhi" } };

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

copy.address.city = "Mumbai";
console.log(original.address.city);   // "Delhi" (safe)

This works for plain data only. If your data has dates, functions, undefined, Map or Set, use structuredClone(original) instead.

4. Hiding private fields before sending data

const user = { id: 1, name: "Riya", password: "secret", token: "abc" };

const publicData = JSON.stringify(user, (key, value) =>
  key === "password" || key === "token" ? undefined : value
);

console.log(publicData);   // {"id":1,"name":"Riya"}

5. Converting a Map to JSON and back

const prices = new Map([["pen", 10], ["book", 120]]);

const text = JSON.stringify([...prices]);
console.log(text);   // [["pen",10],["book",120]]

const restored = new Map(JSON.parse(text));
console.log(restored.get("book"));   // 120

6. A configuration file as a string

const configText = `{
  "appName": "MyCodeNest",
  "version": 2,
  "features": { "darkMode": true, "comments": false }
}`;

const config = JSON.parse(configText);

console.log(config.appName);              // "MyCodeNest"
console.log(config.features.darkMode);    // true

7. Comparing two simple objects

const a = { x: 1, y: 2 };
const b = { x: 1, y: 2 };

console.log(a === b);                                       // false
console.log(JSON.stringify(a) === JSON.stringify(b));       // true

This works only when the keys are in the same order. For a serious comparison, compare property by property.

8. A readable log of an object

const order = { id: 101, items: [{ name: "Pen", qty: 2 }], paid: true };

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

9. Sorting out an array of JSON records

const json = `[
  { "name": "Riya", "score": 82 },
  { "name": "Karan", "score": 67 },
  { "name": "Neha", "score": 91 }
]`;

const students = JSON.parse(json);

const top = students
  .filter((s) => s.score >= 80)
  .map((s) => s.name);

console.log(top);   // ["Riya", "Neha"]

Common mistakes

  • Using single quotes or unquoted keys in JSON. Only "double quotes" are valid: {"name":"Riya"}.
  • Leaving a trailing comma at the end of an object or array.
  • Forgetting that JSON.parse needs a string. JSON.parse(obj) on an object turns it into "[object Object]" and fails.
  • Calling JSON.parse on data you do not control without try...catch. One broken string can stop your whole program.
  • Thinking JSON is a JavaScript object. JSON is text. After stringify, you cannot use .name on it. You must parse it first.
  • Expecting functions, undefined, Map, Set or class methods to survive. They are dropped or changed.
  • Expecting dates to come back as dates. They come back as text. Use a reviver or new Date(text).
  • Parsing the same data twice (JSON.parse(JSON.parse(x))) or stringifying twice. You end up with text inside text.
  • Using the JSON trick for deep copies of complex data. Use structuredClone.
  • Storing secrets in localStorage JSON. Anyone using the browser can read it.

Practice

  1. Create an object with name, age, an array hobbies and a nested address. Convert it to JSON text and print it. Print typeof of the result.
  2. Print the same object pretty-printed with 2 spaces of indentation.
  3. Parse the text '{"city":"Delhi","pin":110001}' and print the city.
  4. Write safeParse(text) that returns null instead of crashing when the text is not valid JSON. Test it with "{ bad json".
  5. Create an object with a password. Use a replacer so that JSON.stringify removes it.
  6. Show what happens to { a: undefined, b: () => 1, c: NaN, d: new Date(0) } after JSON.stringify.
  7. Save a todos array in localStorage and load it back in a second step.
  8. Use a reviver to turn a "created" text into a Date object while parsing.
  9. Make a deep copy using JSON.parse(JSON.stringify(...)), then try the same with structuredClone, and name one case where the JSON trick fails.
  10. Challenge: paste a JSON text with one deliberate mistake into the JSON Formatter, find the problem, and then write the corrected version in your code.

Recap

  • JSON is a text format for data. It has strict rules: double quotes for keys and text, no trailing commas, no comments, and only string, number, boolean, null, array and object values.
  • JSON.stringify(value) turns a JavaScript value into JSON text. Use JSON.stringify(value, null, 2) for readable output.
  • JSON.parse(text) turns JSON text back into a value. Invalid JSON throws a SyntaxError, so wrap data you do not control in try...catch.
  • stringify drops functions, undefined and symbols, turns NaN/Infinity into null, turns dates into ISO text, and fails on circular references and BigInt.
  • A replacer (array or function) filters or changes the output. A reviver changes values while parsing. toJSON() controls how an object is converted.
  • JSON is used everywhere: localStorage, API requests and responses, config files, and quick copies of plain data.
  • Use the JSON Formatter to format, read and debug JSON.
  • Next you will learn dates and time: how to create, read, format and calculate with the Date object.