JavaScript JSON: Parsing and Serializing Data

JSON is the format the web speaks. Learn what it is, how JSON.parse and JSON.stringify work, the gotchas around dates and undefined, and how to handle real data safely.

Published August 9, 202610 min readBy ACY Partner Indonesia
JavaScript JSON — parse and stringify data
300 × 250Ad Space AvailablePlace your ad here

The moment your program needs to talk to anything outside itself — a server, a file, another app — it runs into the same problem: a JavaScript object lives in memory and can’t travel down a network cable. You need a way to turn that object into plain text on the way out, and turn the text back into an object on the way in. That text format is JSON, and it’s the language almost the entire web uses to move data around.

You already know how to build arrays and objects. JSON is what those structures look like once they’ve been flattened into a string you can send or save. In this article you’ll learn what JSON actually is, the two functions that convert between objects and JSON, and the surprising rules that trip people up with dates, undefined, and invalid input.

What is JSON?

JSON stands for JavaScript Object Notation. It’s a lightweight, text-based format for representing structured data — and despite the name, it’s now used far beyond JavaScript. Python, PHP, Go, mobile apps, databases: nearly everything can read and write JSON. It became the default way services exchange data precisely because it’s simple and readable by both humans and machines.

Here’s a small piece of JSON:

{
  "name": "John Doe",
  "age": 28,
  "isMember": true,
  "roles": ["editor", "admin"]
}

If that looks almost identical to a JavaScript object, that’s the whole point — JSON’s syntax was borrowed from JavaScript literals. But “almost identical” is not “identical,” and the differences matter.

JSON is a string, not an object

This is the single most important idea in the whole topic, so let’s be blunt about it: JSON is text. The block above isn’t a JavaScript object — it’s a string that happens to be formatted in the JSON style. You can’t call .name on it or loop over it. It’s just characters until you convert it into a real object.

So in practice you’re always doing one of two things:

  • Serializing (also called stringifying): turning a live JavaScript object into a JSON string, ready to send or store.
  • Parsing: turning a JSON string you received back into a live JavaScript object you can use.

JavaScript gives you exactly one built-in tool for each direction, both hanging off a global object called JSON.

JSON.stringify: object to JSON

JSON.stringify() takes a JavaScript value and returns a JSON string version of it:

const user = {
  name: "John Doe",
  age: 28,
  isMember: true,
};

const json = JSON.stringify(user);

console.log(json);
// '{"name":"John Doe","age":28,"isMember":true}'
console.log(typeof json);
// "string"

Notice the result is one compact line, and typeof json confirms it’s a string. That string is exactly what you’d put in the body of a network request or save to a file. Notice too that every key is now wrapped in double quotes — that’s a hard rule in JSON, which we’ll come back to.

Pretty-printing with indentation

By default stringify gives you that dense single line, which is efficient for machines but painful to read. A third argument controls indentation — pass a number and each level gets that many spaces:

const user = { name: "John Doe", age: 28, roles: ["editor", "admin"] };

console.log(JSON.stringify(user, null, 2));
/*
{
  "name": "John Doe",
  "age": 28,
  "roles": [
    "editor",
    "admin"
  ]
}
*/

The null in the middle is the replacer (more on that in a second); 2 means “indent with two spaces.” This is purely for human eyes — when logging JSON during debugging, JSON.stringify(value, null, 2) is one of the most useful one-liners you’ll ever memorize.

Reading messy JSON

When you receive a long, single-line blob of JSON and need to actually read it, paste it into a JSON formatter to indent and color it. We built a free JSON formatter that pretty-prints and validates in one step — handy when an API hands you a wall of unbroken text and you’re trying to spot the one field that’s wrong.

The replacer argument

That second argument — the replacer — lets you control which properties make it into the output. The most common form is an array of key names to keep:

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

// Only include name and age — drop the password
console.log(JSON.stringify(user, ["name", "age"]));
// '{"name":"John Doe","age":28}'

You can also pass a function as the replacer to transform values on the fly, but the array form covers most real needs — like making sure a sensitive field never leaves your program by accident.

JSON.parse: JSON to object

JSON.parse() is the mirror image: hand it a JSON string and it gives you back a real JavaScript value you can work with:

const json = '{"name":"John Doe","age":28,"isMember":true}';

const user = JSON.parse(json);

console.log(user.name);      // "John Doe"
console.log(user.age + 1);   // 29
console.log(typeof user);    // "object"

After parsing, user is a normal object — you can read user.name with dot notation, do math on user.age, and loop over it like anything else. This is the step that happens whenever your code receives data: a response comes in as a JSON string, you parse it, and now you have an object to work with.

Arrays come through exactly the same way:

const json = '[{"name":"Keyboard","price":250000},{"name":"Mouse","price":120000}]';

const products = JSON.parse(json);

console.log(products.length);      // 2
console.log(products[0].name);     // "Keyboard"

That array-of-objects shape is the most common thing an API returns — a list of records — and parsing turns it straight into an array you can iterate over.

The strict rules of JSON

JSON looks like JavaScript, but it’s a stricter, smaller format. Break a rule and JSON.parse throws an error instead of guessing what you meant. The rules worth burning into memory:

  • Keys must be in double quotes. {"name": "x"} is valid; {name: "x"} is not. Single quotes aren’t allowed either.
  • Strings must use double quotes. 'hello' is invalid JSON; "hello" is required.
  • No trailing commas. [1, 2, 3,] is fine in a JavaScript array but invalid in JSON.
  • No comments. You can’t put // or /* */ inside JSON.
  • No functions, and no undefined. JSON only carries data: strings, numbers, booleans, null, arrays, and objects.
// VALID JSON
'{"active": true, "count": 3, "tags": ["a", "b"]}'

// INVALID JSON — single quotes, unquoted key, trailing comma
"{name: 'John', age: 28,}"

JSON.parse throws on bad input

If you feed JSON.parse a string that isn’t valid JSON, it doesn’t return null or undefined — it throws a SyntaxError and stops your code in its tracks. A truncated network response, an empty string, or a stray comma is enough to do it. Since you rarely control the exact text you receive, you should treat parsing as something that can fail and wrap it in a guard. We’ll see how next.

Parsing safely with try…catch

Because JSON.parse throws, you wrap it in a try...catch block whenever the input comes from somewhere you don’t fully control — a server, user input, a file. That way a bad response degrades gracefully instead of crashing the whole page:

function safeParse(text) {
  try {
    return JSON.parse(text);
  } catch (err) {
    console.error("Invalid JSON:", err.message);
    return null;
  }
}

console.log(safeParse('{"ok": true}'));   // { ok: true }
console.log(safeParse("not json"));        // null  (and logs the error)

Now the caller just checks whether they got null back, instead of the entire script blowing up on one malformed response. If try...catch is new to you, the error handling article walks through it in detail — and JSON parsing is one of the most natural places to reach for it.

Gotchas: dates, undefined, and lost types

JSON can only represent a handful of basic types. Anything outside that set gets converted or quietly dropped on the way out, which leads to a few classic surprises.

undefined and functions disappear

When you stringify an object, any property whose value is undefined or a function is simply omitted from the output — no error, it just vanishes:

const data = {
  name: "John Doe",
  nickname: undefined,
  greet: function () { return "hi"; },
};

console.log(JSON.stringify(data));
// '{"name":"John Doe"}'   — nickname and greet are gone

Dates become strings

A Date object doesn’t survive a round trip. stringify converts it to an ISO string, and parse has no way to know it was ever a date — you get a plain string back:

const event = { title: "Launch", when: new Date("2026-08-09") };

const json = JSON.stringify(event);
console.log(json);
// '{"title":"Launch","when":"2026-08-09T00:00:00.000Z"}'

const restored = JSON.parse(json);
console.log(typeof restored.when);   // "string", not a Date!

So after parsing, if you need a real Date, you have to rebuild it yourself: new Date(restored.when). This catches a lot of people — they stringify a date, parse it back, and wonder why date methods suddenly don’t work.

JSON only carries plain data

The mental model that keeps you out of trouble: JSON is a data format, not a JavaScript snapshot. It knows strings, numbers, booleans, null, arrays, and objects — and nothing else. Dates, functions, undefined, Map, Set, class instances — none of those survive intact. When a value comes back “wrong” after a round trip, this is almost always why, and the fix is to reconstruct the rich type yourself after parsing.

Deep-cloning with JSON (and its limits)

There’s a popular trick that falls out of all this: stringify an object and immediately parse it back, and you get a brand-new, fully independent copy — a deep clone:

const original = { user: { name: "John Doe" }, tags: ["a", "b"] };

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

copy.user.name = "Jane Doe";
console.log(original.user.name);   // "John Doe" — original is untouched

Changing the copy doesn’t affect the original, even for nested objects — which a simple { ...original } spread can’t promise. It’s quick and works for plain data. But remember the gotchas above: this trick silently loses dates, undefined, and functions. For plain JSON-safe data it’s fine; for anything richer, modern JavaScript has a built-in structuredClone() that handles dates and more, and is the better choice when it’s available.

A realistic round trip

Let’s put both directions together the way you’d actually use them — build an object, serialize it to send, then parse a response:

// 1. You have a live object
const order = {
  customer: "Jane Doe",
  items: [
    { name: "Keyboard", qty: 1 },
    { name: "Mouse", qty: 2 },
  ],
};

// 2. Serialize it to send to a server
const payload = JSON.stringify(order);
// '{"customer":"Jane Doe","items":[{"name":"Keyboard","qty":1},...]}'

// 3. A response comes back as a JSON string
const responseText = '{"orderId":7421,"status":"confirmed"}';

// 4. Parse it to use the data
const result = JSON.parse(responseText);
console.log(result.status);   // "confirmed"

That out-and-back flow — stringify to send, parse to receive — is the everyday rhythm of working with data on the web. When you start using the Fetch API to talk to real servers, this is exactly the dance you’ll be doing on every request.

Wrapping up

JSON is how structured data travels between programs, and two functions cover the whole job:

  • JSON is a text format for structured data — borrowed from JavaScript’s syntax, but used by nearly every language and service. A JSON string is text, not a usable object, until you parse it.
  • JSON.stringify(value) serializes an object into a JSON string. Pass (value, null, 2) to pretty-print it with indentation.
  • JSON.parse(text) turns a JSON string back into a real JavaScript value you can use.
  • JSON has strict rules: double-quoted keys and strings, no trailing commas, no comments, no functions or undefined. Break one and parse throws — so wrap untrusted input in try...catch.
  • It only carries plain data. Dates become strings, and undefined/functions are dropped. Rebuild rich types yourself after parsing.
  • JSON.parse(JSON.stringify(obj)) is a quick deep clone for JSON-safe data, with those same limits.

With serializing and parsing under your belt, you’re ready for the next step: actually fetching data from a server. JSON is the format that data arrives in, so everything you learned here plugs straight into working with Promises and the Fetch API, which are coming up next.

Tags:javascriptfrontendjsondataintermediate
728 × 90Ad Space AvailablePlace your ad here

Related Articles

See All Articles

You Might Also Like

Frontend best practices overview cover
Frontend / Fundamentals

Frontend Best Practices: An Overview

A friendly map of what good frontend really means — semantic HTML, clean CSS, unobtrusive JavaScript, responsive layouts, performance, and progressive enhancement, with pointers to go deeper.

Sep 20, 20268 min read
A Frontend Developer Roadmap cover with the path HTML to CSS to JavaScript
Frontend / Fundamentals

A Frontend Developer Roadmap: What to Learn, and in What Order

A calm, step-by-step learning path for beginners: HTML, CSS, JavaScript, developer tools, responsive and accessible design, a framework, TypeScript, and deployment, with the reasoning behind each step.

Sep 20, 202611 min read
Title card reading Styling and Interactivity over a dark blue ACY Partner background
Frontend / Fundamentals

How Styling and Interactivity Work

A beginner-friendly look at how CSS turns plain HTML into a designed layout, and how JavaScript adds behavior — the structure, style, behavior mental model for building web pages.

Sep 20, 20269 min read
Three front-end layers combining on one web page
Frontend / Fundamentals

How HTML, CSS, and JavaScript Work Together

A hands-on walkthrough for beginners: build one small button, give it structure with HTML, looks with CSS, and behavior with JavaScript, and watch the three layers cooperate on a real page.

Sep 20, 20268 min read
The Frontend Developer Toolkit cover with editor, browser, and CLI motifs
Frontend / Fundamentals

The Frontend Developer Toolkit

A friendly tour of the everyday tools a frontend developer relies on — code editor, browser and DevTools, terminal, version control, package managers, and a dev server — and what each one is actually for.

Sep 20, 202610 min read
Cover illustration for What Frontend Developers Do
Frontend / Fundamentals

What Frontend Developers Do: A Beginner's Guide to the Role

A clear, beginner-friendly look at what frontend developers actually do every day: turning designs into working interfaces, building reusable UI, and caring about responsiveness, accessibility, and speed.

Sep 20, 202610 min read