Advanced JSON Stringify Techniques: Replacer, Space, and Custom Serialization
Most developers use JSON Stringify for simple conversions, but it offers far more control and flexibility through optional parameters and custom serialization logic. These advanced techniques let you transform data, filter sensitive fields, format output, handle edge cases, and even define how custom objects serialize themselves.
In this guide, we'll explore the replacer function, the space parameter, custom toJSON methods, and best practices for advanced JSON serialization in JavaScript.
Overview of JSON Stringify Advanced Features
The full signature of JSON Stringify reveals its power:
JSON.stringify(value, replacer, space)
While most developers use only the first argument, the second and third parameters unlock powerful transformations:
- replacer: A function or array that controls which properties are included and how they're transformed.
- space: A number or string that adds indentation for pretty-printing.
You can also define custom toJSON methods on your objects to control exactly how they serialize.
Must Read: What Is JSON Stringify? Complete Guide with Examples
Using the Replacer Function for Filtering and Transformation
The replacer parameter can be a function that gets called for every key–value pair during serialization.
Function signature:
function replacer(key, value) { // return modified value or undefined to exclude }
Filtering sensitive fields
const user = { name: "Alex", email: "alex@example.com", password: "secret123", apiKey: "sk_live_abc123" }; const safeJson = JSON.stringify(user, (key, value) => { if (key === "password" || key === "apiKey") return undefined; return value; }); console.log(safeJson); // → {"name":"Alex","email":"alex@example.com"}
Sensitive data like passwords, API keys, or tokens can be excluded before logging or sending to external systems.
Transforming values during serialization
const product = { name: "Laptop", price: 1200.5, inStock: true }; const transformed = JSON.stringify(product, (key, value) => { if (key === "price") return `$${value.toFixed(2)}`; return value; }); console.log(transformed); // → {"name":"Laptop","price":"$1200.50","inStock":true}
You can format numbers, modify strings, or convert values on the fly.
Using an array as a replacer
When replacer is an array, it defines a whitelist of properties to include:
const data = { id: 101, name: "Product A", price: 50, internal: "confidential" }; const publicData = JSON.stringify(data, ["id", "name", "price"]); console.log(publicData); // → {"id":101,"name":"Product A","price":50}
This is cleaner than a function when you only want to select specific fields.
Using the Space Parameter for Pretty-Printing
The space parameter controls indentation, making JSON output human-readable.
Syntax:
JSON.stringify(value, null, space)
- space can be a number (0–10) or a string (up to 10 characters).
- A number adds that many spaces per indentation level.
- A string uses that text for indentation.
Example: Adding spaces
const obj = { name: "Alex", age: 28, active: true }; console.log(JSON.stringify(obj, null, 2));
Output:
{ "name": "Alex", "age": 28, "active": true }
Example: Using a custom indentation string
console.log(JSON.stringify(obj, null, "→ "));
Output:
{ → "name": "Alex", → "age": 28, → "active": true }
Pretty-printing is essential for debugging, logging, or generating readable JSON files.
Custom Serialization with toJSON Methods
Objects can define a toJSON method that controls how they serialize. JSON Stringify automatically calls this method if it exists.
Basic example
const user = { username: "alex", password: "secret123", toJSON() { return { username: this.username }; } }; console.log(JSON.stringify(user)); // → {"username":"alex"}
The toJSON method excluded the password automatically.
Working with Date objects
JavaScript Date objects already include a toJSON method that returns an ISO 8601 string:
const event = { name: "Launch", date: new Date("2025-12-31T23:59:59Z") }; console.log(JSON.stringify(event)); // → {"name":"Launch","date":"2025-12-31T23:59:59.000Z"}
You can override toJSON on custom date wrappers to control the format.
Custom class serialization
class Product { constructor(id, name, price) { this.id = id; this.name = name; this.price = price; this.createdAt = new Date(); } toJSON() { return { id: this.id, name: this.name, price: `$${this.price.toFixed(2)}` }; } } const item = new Product(1, "Widget", 19.99); console.log(JSON.stringify(item)); // → {"id":1,"name":"Widget","price":"$19.99"}
This pattern keeps serialization logic encapsulated within the class.
Handling Special Cases and Edge Cases
Dealing with undefined, functions, and symbols
const obj = { name: "Alex", temp: undefined, log: () => {}, [Symbol("id")]: 123 }; console.log(JSON.stringify(obj)); // → {"name":"Alex"}
All three types are omitted from the output because JSON only supports data, not behavior or meta-values.
Handling circular references
const obj = { name: "Alex" }; obj.self = obj; try { JSON.stringify(obj); } catch (err) { console.log(err.message); // → Converting circular structure to JSON }
You must remove or replace circular references manually, or use a library like flatted.
Serializing Map and Set objects
Maps and Sets do not serialize to meaningful JSON by default:
const map = new Map([["key", "value"]]); console.log(JSON.stringify(map)); // → {}
You must convert them to arrays first:
const serialized = JSON.stringify(Array.from(map.entries())); console.log(serialized); // → [["key","value"]]
Handling BigInt
BigInt values are not supported by JSON Stringify:
const big = { id: 123n }; JSON.stringify(big); // TypeError: Do not know how to serialize a BigInt
Convert BigInt to a string manually before stringifying.
Combining Replacer, Space, and toJSON
You can combine all three techniques for maximum control:
class User { constructor(name, password, createdAt) { this.name = name; this.password = password; this.createdAt = createdAt; } toJSON() { return { name: this.name, createdAt: this.createdAt.toISOString() }; } } const user = new User("Alex", "secret", new Date()); const output = JSON.stringify( user, (key, value) => (key === "createdAt" ? value.slice(0, 10) : value), 2 ); console.log(output);
Output:
{ "name": "Alex", "createdAt": "2025-12-15" }
This example combines:
- toJSON for initial control
- replacer for further transformation
- space for readable formatting
Real-World Use Cases for Advanced JSON Stringify
API payloads with field filtering
const sendUserData = (user) => { const payload = JSON.stringify(user, ["id", "name", "email"]); fetch("/api/users", { method: "POST", headers: { "Content-Type": "application/json" }, body: payload }); };
Logging with pretty-print
console.log("State:", JSON.stringify(state, null, 2));
Exporting configuration files
const config = { theme: "dark", lang: "en", debug: false }; fs.writeFileSync("config.json", JSON.stringify(config, null, 2));
Sanitizing data before transmission
const clean = JSON.stringify(data, (k, v) => typeof v === "string" ? v.trim() : v );
Best Practices for Advanced JSON Stringify
- Use replacer functions to exclude sensitive data or transform values.
- Use space for debugging and file exports, but omit it for production APIs to save bytes.
- Define toJSON methods on classes for clean, reusable serialization logic.
- Always handle circular references, undefined, and BigInt before stringifying.
- Validate serialized output before sending to external systems.
- Combine techniques (replacer + space + toJSON) for complex use cases.
Conclusion: Unlock the Full Power of JSON Stringify
JSON Stringify is far more than a simple object-to-string converter. With replacer functions, the space parameter, and custom toJSON methods, you can filter, transform, format, and control every aspect of JSON serialization in JavaScript.
By mastering these advanced techniques, you'll write safer APIs, cleaner logs, and more maintainable code.
Tools on JSON Kithub help:
- Convert YAML to JSON
- Convert JSON to YAML
- Stringify JSON
- Parse JSON
- JSON formatter
- Compare JSON
- JSON Validator
- Minify JSON
- JSON Escape
- JSON Unescape
- Convert JSON to TOON
- Convert TOON to JSON
FAQs On Advanced JSON Stringify Techniques
Q1. What is the replacer parameter in JSON Stringify?
The replacer can be a function or array that controls which properties are included in the output and how values are transformed during serialization.
Q2. How do I pretty-print JSON with JSON Stringify?
Use the third space parameter, such as JSON.stringify(obj, null, 2), to add indentation and make the JSON output more readable.
Q3. What is a toJSON method?
A toJSON method is a custom function you define on an object that controls how that object serializes when passed to JSON Stringify.
Q4. Can I filter out sensitive fields with JSON Stringify?
Yes. Use a replacer function to return undefined for any key you want to exclude, such as password or apiKey.
Q5. How do I handle circular references in JSON Stringify?
You must manually remove or replace circular references before calling JSON Stringify, or use a library like flatted that supports circular structures.
Ready to Try Our JSON Tools?
Format, validate, and transform your JSON data with our free online tools.