AllJSONTools

Free JSON Developer Tools

How to Parse JSON in JavaScript: The Complete Guide

2026-02-26 · 12 min read · By AllJSONTools

JavaScript
JSON
Tutorial
Having JSON issues?

Paste broken JSON and fix it instantly with AI — plain-English explanations included.

Fix JSON with AI

The Basics: JSON.parse() and JSON.stringify()

JavaScript has two built-in methods for working with JSON. They ship in every browser and Node.js runtime — no libraries required.

javascript
// Parse a JSON string into a JavaScript object
const json = '{"name": "Jane", "age": 28}';
const user = JSON.parse(json);
console.log(user.name); // "Jane"

// Convert a JavaScript object into a JSON string
const obj = { name: "Jane", age: 28 };
const str = JSON.stringify(obj);
console.log(str); // '{"name":"Jane","age":28}'

That covers 90% of use cases. The rest of this guide covers the edge cases, gotchas, and advanced patterns you’ll hit in production.

Always Wrap JSON.parse() in try/catch

JSON.parse() throws a SyntaxError if the input is not valid JSON. If you don’t catch it, your entire function crashes.

javascript
function safeParse(jsonString) {
  try {
    return { data: JSON.parse(jsonString), error: null };
  } catch (err) {
    return { data: null, error: err.message };
  }
}

const result = safeParse('{"broken": }');
if (result.error) {
  console.error("Invalid JSON:", result.error);
} else {
  console.log(result.data);
}

This is especially important when parsing user input, API responses, or data from localStorage. Use the JSON Formatter to quickly validate and debug malformed JSON strings.

The Reviver Function

JSON.parse() accepts an optional second argument — a reviver function that transforms each key-value pair during parsing. The most common use: converting date strings into Date objects.

javascript
const json = '{"name": "Jane", "createdAt": "2026-02-25T10:30:00Z"}';

const user = JSON.parse(json, (key, value) => {
  // Convert ISO date strings to Date objects
  if (typeof value === "string" && /^d{4}-d{2}-d{2}T/.test(value)) {
    return new Date(value);
  }
  return value;
});

console.log(user.createdAt instanceof Date); // true
console.log(user.createdAt.getFullYear());   // 2026

JSON.stringify() Options

JSON.stringify() accepts two optional arguments: a replacer (to filter or transform values) and a space parameter (for pretty-printing).

javascript
const user = {
  name: "Jane",
  password: "secret123",
  role: "admin",
  createdAt: new Date("2026-02-25"),
};

// Pretty-print with 2-space indentation
console.log(JSON.stringify(user, null, 2));

// Filter out sensitive fields with a replacer
const safe = JSON.stringify(user, (key, value) => {
  if (key === "password") return undefined; // omit
  return value;
}, 2);

console.log(safe);
// {
//   "name": "Jane",
//   "role": "admin",
//   "createdAt": "2026-02-25T00:00:00.000Z"
// }

// Or pass an array of allowed keys
const filtered = JSON.stringify(user, ["name", "role"]);
console.log(filtered); // '{"name":"Jane","role":"admin"}'

Parsing JSON from APIs with fetch()

The fetch() API returns a Response object with a built-in .json() method that parses the body as JSON.

javascript
async function getUser(id) {
  const response = await fetch(`https://api.example.com/users/${id}`);

  // Always check the status before parsing
  if (!response.ok) {
    throw new Error(`HTTP ${response.status}: ${response.statusText}`);
  }

  const data = await response.json();
  return data;
}

// POST with a JSON body
async function createUser(user) {
  const response = await fetch("https://api.example.com/users", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(user),
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(error.message);
  }

  return response.json();
}

Note: response.json() returns a Promise. It can also throw if the response body is not valid JSON, so handle that case in production code.

Deep Cloning with JSON

A common trick is using JSON.parse(JSON.stringify(obj)) to deep-clone an object. It works, but has limitations:

javascript
const original = { name: "Jane", scores: [10, 20, 30] };
const clone = JSON.parse(JSON.stringify(original));

clone.scores.push(40);
console.log(original.scores); // [10, 20, 30] — not affected

// But it loses non-JSON types:
const problematic = {
  date: new Date(),       // becomes a string
  regex: /abc/,           // becomes {}
  func: () => {},         // gets dropped
  undef: undefined,       // gets dropped
  nan: NaN,               // becomes null
  infinity: Infinity,     // becomes null
};

For modern JavaScript, prefer structuredClone(obj) which handles Date, Map, Set, ArrayBuffer, and more. The JSON trick is still useful when you specifically want a JSON-safe snapshot.

Type-Safe JSON Parsing in TypeScript

JSON.parse() returns any, which defeats TypeScript’s type system. Use a validation library like Zod to parse and validate in one step:

javascript
import { z } from "zod";

const UserSchema = z.object({
  name: z.string(),
  email: z.string().email(),
  age: z.number().int().positive(),
});

type User = z.infer<typeof UserSchema>;

function parseUser(json: string): User {
  const raw = JSON.parse(json);
  return UserSchema.parse(raw); // throws ZodError if invalid
}

// Safe version
function safeParseUser(json: string) {
  try {
    const raw = JSON.parse(json);
    return UserSchema.safeParse(raw);
  } catch {
    return { success: false, error: "Invalid JSON" };
  }
}

Generate Zod schemas from your API responses automatically with the JSON to Zod converter, or create TypeScript interfaces with JSON to TypeScript.

Handling Large JSON

JSON.parse() loads the entire string into memory and blocks the main thread while parsing. For large payloads (10MB+), consider these strategies:

  • Streaming parsers — Libraries like stream-json (Node.js) parse JSON incrementally without loading it all at once.

  • Web Workers — Move JSON.parse() to a Web Worker so parsing doesn’t block the UI thread.

  • Paginate at the API level — The best fix for large JSON is not to send it. Use pagination and field selection to keep payloads small.

Querying JSON with JSONPath

When you need to extract specific values from complex, nested JSON without writing loops, use JSONPath — a query language for JSON similar to XPath for XML.

javascript
import { JSONPath } from "jsonpath-plus";

const data = {
  store: {
    books: [
      { title: "Dune", price: 12.99 },
      { title: "Neuromancer", price: 9.99 },
      { title: "Snow Crash", price: 14.99 },
    ]
  }
};

// Get all book titles
const titles = JSONPath({ path: "$.store.books[*].title", json: data });
console.log(titles); // ["Dune", "Neuromancer", "Snow Crash"]

// Get books under $13
const cheap = JSONPath({ path: "$.store.books[?(@.price < 13)]", json: data });

Test JSONPath expressions interactively with the JSONPath Query tool, and check the JSONPath Cheatsheet for the full syntax reference.

Common Mistakes

  1. Double-parsing — Calling JSON.parse() on something that’s already an object. This happens when an API response is auto-parsed by the HTTP client.

  2. Trailing commas — Valid in JavaScript but invalid in JSON. {"a": 1,} will throw.

  3. Single quotes — JSON requires double quotes. {'a': 1} is not valid JSON.

  4. Circular references JSON.stringify() throws on circular objects. Use a replacer or a library to handle them.

  5. Losing precision on large numbers — JavaScript numbers are 64-bit floats. Integers larger than 2^53 - 1 lose precision when parsed. Use BigInt or keep them as strings.

When you hit a parsing error, paste your JSON into the JSON Formatter — it will pinpoint the exact line and character where the syntax breaks.

Having JSON issues?

Paste broken JSON and fix it instantly with AI — plain-English explanations included.

Fix JSON with AI