JSON.stringify Tutorial: JavaScript Objects to JSON

Last updated:

JSON.stringify() serializes a JavaScript value to a JSON string using 3 parameters: the value, an optional replacer (filter array or transform function), and a space argument — pass 2 for 2-space indented output. V8 stringifies 100k small objects per second; a 1 MB object graph finishes in under 5 ms in Node.js 18+. There are 4 categories of values silently dropped or coerced:undefined, functions, and Symbols in object properties are omitted; those 3 types inside arrays become null; NaN and Infinity also become null; and BigInt throws a TypeError. This guide covers all 3 parameters, the toJSON() hook, circular reference handling, and replacer functions for filtering sensitive fields.

Four categories of values are silently dropped or coerced: object properties whose value is undefined, a function, or a symbol are omitted entirely; those same values inside arrays become null to preserve array length; NaN, Infinity, and -Infinity also become null; and BigInt throws a TypeError unless converted first. This page covers all three parameters, serialization edge cases, and the toJSON() hook.

Basic JSON.stringify usage

Pass a JavaScript object, array, string, number, boolean, or null toJSON.stringify(). The return value is a JSON string.

const user = {
  id: 42,
  name: 'Alice',
  active: true,
  roles: ['admin', 'editor']
}

const json = JSON.stringify(user)
console.log(json)
// {"id":42,"name":"Alice","active":true,"roles":["admin","editor"]}

The output has no extra whitespace by default. That is ideal for network payloads and storage, but hard to read during debugging.

Pretty print JSON with spacing

The third argument controls indentation. Use 2 spaces for readable JSON.

JSON.stringify(user, null, 2)

// {
//   "id": 42,
//   "name": "Alice",
//   "active": true,
//   "roles": [
//     "admin",
//     "editor"
//   ]
// }

You can also pass a string for indentation, but spaces are the safest default for JSON files committed to a repository.

Use a replacer array to keep selected fields

The second argument can be an array of property names. Only those keys are included.

const user = {
  id: 42,
  name: 'Alice',
  email: 'alice@example.com',
  passwordHash: 'secret'
}

JSON.stringify(user, ['id', 'name'], 2)

// {
//   "id": 42,
//   "name": "Alice"
// }

This is useful for small allowlists, but it applies by property name at every nesting level. For conditional logic, use a replacer function instead.

Use a replacer function to transform values

A replacer function runs for every key and value. Return undefined to omit a property from objects.

const safeJson = JSON.stringify(user, (key, value) => {
  if (key === 'passwordHash') return undefined
  if (key === 'email') return String(value).toLowerCase()
  return value
}, 2)

Replacers are good for removing secrets, normalizing values, and creating stable debug output. Do not use them as your only security layer for API responses; filter sensitive fields before serialization too.

Values JSON.stringify changes or drops

  • undefined, functions, and symbols are omitted from objects.
  • Inside arrays, undefined, functions, and symbols become null.
  • Date objects serialize to ISO strings through toJSON().
  • NaN, Infinity, and -Infinity become null.
  • BigInt throws unless you convert it to a string or number first.
JSON.stringify({
  missing: undefined,
  fn: () => true,
  badNumber: NaN,
  createdAt: new Date('2024-01-15T10:30:00Z')
}, null, 2)

// {
//   "badNumber": null,
//   "createdAt": "2024-01-15T10:30:00.000Z"
// }

Circular references throw an error

JSON is a tree format. It cannot represent objects that point back to themselves.

const user = { name: 'Alice' }
user.self = user

JSON.stringify(user)
// TypeError: Converting circular structure to JSON

For logs, strip circular fields or use a purpose-built safe stringifier. For data exchange, redesign the payload so references are represented by IDs.

Format and validate JSON output

Paste stringified output into Jsonic's JSON Formatter to pretty print, validate, or minify it. Everything runs in your browser.

Open JSON Formatter

Frequently asked questions

What values does JSON.stringify skip or convert?

Inside objects, undefined, functions, and symbols are omitted entirely. Inside arrays, those values become null. NaN and Infinity also become null. BigInt throws unless converted first. Dateobjects serialize to ISO strings via toJSON().

How do I pretty print with JSON.stringify?

Pass a number as the third argument: JSON.stringify(value, null, 2) for two spaces. You can also pass a string like '\t' for tabs. The number is capped at 10.

What is a replacer function?

The second argument can be a function that runs for each key-value pair. Returnundefined to omit a property, or return a different value to transform it. An array of strings acts as an allowlist of keys to include.

How do I handle circular references?

JSON.stringify throws a TypeError for circular structures. Use a replacer that tracks seen objects and returns undefined for duplicates, or use a library likeflatted for a serializable format.

How do I stringify a Date object?

Date objects serialize automatically to ISO 8601 strings because they have a toJSON()method. The result is a string in JSON. Use a reviver in JSON.parse to restore it as a Date when reading back.

What is the toJSON method?

If an object defines toJSON(), JSON.stringify calls it and serializes the returned value instead. Add it to your own classes to control serialization and omit private fields automatically.

Further reading and primary sources