What you'll be able to do

By the end of this page you should be able to serialize a plain object with JSON.stringify, rebuild it with JSON.parse, handle bad JSON safely, and name a few things JSON cannot carry (functions, undefined, symbols).

Previous post: type coercion surprises.

Who this is for

  • People saving settings to localStorage as text
  • Beginners who copy API responses and want them as objects
  • Anyone who saw Unexpected token and did not know where to look

You can skip this if you already parse with try/catch and know JSON’s limits. Come back when JSON.parse crashes your page on user input.

JSON is text, not a live object

const user = { name: "Asha", role: "editor" };
const text = JSON.stringify(user);
console.log(text); // '{"name":"Asha","role":"editor"}'
console.log(typeof text); // "string"

Scenario A — send data to an API. HTTP bodies are often JSON text.

Scenario B — save in localStorage. Storage holds strings; stringify first.

JSON.parse: text back to data

const text = '{"name":"Asha","role":"editor"}';
const user = JSON.parse(text);
console.log(user.name); // "Asha"

Scenario A — read API response (after you have the string — fetch + .json() wraps this later).

Scenario B — load saved settings from localStorage.getItem("settings").

Parse errors are runtime errors

try {
  JSON.parse("{ bad");
} catch (err) {
  console.log("Invalid JSON:", err.message);
}

Scenario A — user pasted broken JSON in a tool. Catch and show a message — same spirit as Blog #22.

Scenario B — empty string. JSON.parse("") throws. Check length or catch.

What JSON drops or changes

const data = {
  name: "Asha",
  meta: undefined,
  updated: new Date(),
  go: function () {},
};
console.log(JSON.stringify(data));
// {"name":"Asha","updated":"2026-08-13T..."} — no meta, no go

Scenario A — plain settings object. Strings, numbers, booleans, null, arrays, nested objects — fine.

Scenario B — methods on an object. JSON is data-only; functions vanish on stringify.

Dates become ISO strings — parse gives strings back, not Date objects, unless you convert.

JSON.stringify with spacing (readable logs)

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

Scenario A — debug in the console. Pretty print helps humans.

Scenario B — production payloads. Usually compact one-line JSON is fine.

A tiny practice file

Save as json-practice.html.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>JSON</title>
  </head>
  <body>
    <textarea id="raw" rows="4" cols="40">{"title":"Hello"}</textarea>
    <button id="parse">Parse</button>
    <pre id="out"></pre>
    <script>
      document.getElementById("parse").addEventListener("click", function () {
        const raw = document.getElementById("raw").value;
        try {
          const data = JSON.parse(raw);
          document.getElementById("out").textContent =
            "OK: " + JSON.stringify(data, null, 2);
        } catch (err) {
          document.getElementById("out").textContent = "Error: " + err.message;
        }
      });
    </script>
  </body>
</html>

Mistakes I see a lot

1. JSON.parse on untrusted input without try/catch.

2. Expecting functions or undefined to survive stringify.

3. Double-stringifying. JSON.stringify(JSON.stringify(obj)) — usually accidental.

4. Assuming parse returns Dates. It returns plain objects unless you revive.

5. Storing huge blobs in localStorage without thinking about size limits.

6. Using JSON clone for everything. Remember structuredClone for in-memory copies; JSON for wire/storage.

What to try before the next post

  1. Stringify a small object; parse it back; compare fields.
  2. Break the JSON on purpose; catch the error.
  3. Stringify an object with undefined and a function; see what disappears.
  4. Build the tiny HTML file.

Next in this series: Set and Map basics — unique values and key–value maps without array hacks.

Try this next outside the series

Objects and references click faster when you connect them to state, payloads, and database-shaped data.