JSON Stringify Online
Convert a JSON object to an escaped string literal — exactly what JSON.stringify() produces.
JSON.stringify() converts a JavaScript object, array, or value into a JSON-formatted string — wrapping it in double quotes and escaping all special characters. The result is a portable text representation that can be stored in localStorage, sent as an HTTP request body, embedded in a URL, or used as a string value inside another JSON object.
What Is JSON.stringify()?
JSON.stringify() is a JavaScript method that converts a JavaScript object, array, or value into a JSON-formatted string. This process is called serialisation — turning structured in-memory data into a flat, portable text representation that can cross system boundaries: stored in a database, sent over HTTP, saved to a file, or embedded in another data structure.
The operation is the direct inverse of JSON.parse(). Where parse converts a string into an object (deserialisation), stringify converts an object into a string (serialisation). Together they form the JSON round-trip: object → string → object.
This tool replicates JSON.stringify(JSON.stringify(value)) — it first parses your input to validate it, then serialises it to a compact JSON string, then stringifies that string so you see the escaped string literal including the wrapping double quotes. Use Unstringify mode to reverse the operation. For full parse analysis, visit the JSON Parser.
Quick Facts
Before & After: Object to String
Here is exactly what JSON.stringify() does to a simple object — note how every internal double quote becomes \" and the whole result is wrapped in outer quotes.
{
"name": "Alice Chen",
"age": 30,
"active": true,
"note": "line one\nline two"
}"{"name":"Alice Chen","age":30,"active":true,"note":"line one\\nline two"}"The outer "...\"" are the string delimiters. All inner " become \". The literal \n in the value becomes \\n.
What Gets Escaped
JSON.stringify must escape certain characters inside string values to produce a valid JSON string literal. Here is every character that is transformed:
| Character | Raw form | Escaped form | Why it must be escaped |
|---|---|---|---|
| Double quote | " | \" | Would terminate the string early |
| Backslash | \ | \\ | Escape character — must be doubled |
| Line feed | ↵ (LF) | \n | Strings cannot span lines in JSON |
| Carriage return | ↵ (CR) | \r | Strings cannot span lines in JSON |
| Tab | → (tab) | \t | Control character not allowed in strings |
| Form feed | FF | \f | Control character not allowed in strings |
| Backspace | BS | \b | Control character not allowed in strings |
| Other control chars | U+0000–U+001F | \uXXXX | RFC 8259 §7 — must be escaped |
Non-ASCII characters (like emoji or accented letters) are not escaped by default — they are included as-is in the output. This is valid per RFC 8259 which mandates UTF-8. You can force Unicode escaping with a custom replacer if you need ASCII-safe output.
The Three Parameters of JSON.stringify()
JSON.stringify(value, replacer, space) — most developers only use the first argument, but the other two are powerful.
valueThe data to serialise
Any JavaScript value: object, array, string, number, boolean, or null. Functions, Symbols, and undefined are not valid JSON — they are either omitted (in objects) or cause stringify to return undefined (at the top level).
replacerFilter or transform values
Pass an array of key names to act as an allowlist, or a function that is called for every key-value pair during serialisation.
// Array replacer — only include these keys
JSON.stringify(user, ['name', 'email'])
// {"name":"Alice","email":"alice@example.com"}
// Function replacer — omit sensitive fields
JSON.stringify(user, (key, val) => {
if (key === 'password') return undefined; // omit
return val; // keep everything else
})spaceControl indentation
A number (spaces per level) or a string (used as the indent). Without this argument, output is compact — the same as JSON minification.
JSON.stringify(obj) // compact (minified)
JSON.stringify(obj, null, 2) // 2-space indented (pretty-print)
JSON.stringify(obj, null, 4) // 4-space indented
JSON.stringify(obj, null, '\t') // tab-indentedEdge Cases & Gotchas
JSON.stringify has several non-obvious behaviours that cause bugs. Know them before they hit you in production.
undefined, functions, and Symbols are silently dropped
expand_more
const obj = { name: 'Alice', fn: () => {}, sym: Symbol('x'), val: undefined };
JSON.stringify(obj);
// '{"name":"Alice"}' — fn, sym, val silently omittedNote: If your object has an undefined value you need preserved, convert it to null first.
Dates are converted to ISO strings
expand_more
JSON.stringify({ created: new Date('2026-04-26') });
// '{"created":"2026-04-26T00:00:00.000Z"}'
// JSON.parse() gives back a string, NOT a Date objectNote: Dates survive the trip to string but parse back as strings — you must reconstruct the Date yourself.
Circular references throw a TypeError
expand_more
const a = {};
a.self = a; // circular
JSON.stringify(a);
// TypeError: Converting circular structure to JSONNote: Use a library like flatted or fast-json-stable-stringify for objects with circular references.
BigInt throws a TypeError
expand_more
JSON.stringify({ n: 9007199254740993n });
// TypeError: Do not know how to serialize a BigIntNote: Convert BigInt to string or number before stringifying, or use a replacer that handles it.
toJSON() enables custom serialisation
expand_more
const obj = {
value: 42,
toJSON() { return { serialised: this.value }; }
};
JSON.stringify(obj);
// '{"serialised":42}'Note: If a value has a toJSON() method, JSON.stringify calls it and serialises the returned value instead.
Stringifying Nested Objects & Arrays
Regardless of how deeply nested a JSON object is, JSON.stringify() flattens everything into a single linear string. Every double quote at every nesting level gets escaped — and nesting depth has no effect on the output structure.
{
"orders": [
{
"id": "ord-001",
"customer": {
"name": "Alice Chen",
"email": "alice@example.com"
},
"items": [
{ "sku": "WGT-PRO", "qty": 2 }
],
"paid": true
}
],
"meta": { "page": 1, "total": 1 }
}"{"orders":[{"id":"ord-001","customer":{"name":"Alice Chen","email":"alice@example.com"},"items":[{"sku":"WGT-PRO","qty":2}],"paid":true}],"meta":{"page":1,"total":1}}"Every " at every depth — including inside the customer and items objects — is escaped to \".
A key insight: array items are not individually escaped — the entire array structure is preserved as JSON, just with quotes escaped. The array brackets [ and ] do not need escaping (they are not JSON string delimiters), so they pass through as-is.
Common pattern: localStorage with nested state
// Storing nested application state
const appState = {
user: { id: 4821, name: 'Alice', role: 'admin' },
prefs: { theme: 'dark', lang: 'en-US', notifications: true },
cart: [{ id: 'WGT-PRO', qty: 2 }, { id: 'GDG-PLS', qty: 1 }],
};
// Stringify the whole object tree — nesting is preserved
localStorage.setItem('app-state', JSON.stringify(appState));
// Reading back — JSON.parse reconstructs the full nested structure
const stored = localStorage.getItem('app-state');
const state = stored ? JSON.parse(stored) : {};
console.log(state.user.name); // 'Alice'
console.log(state.cart.length); // 2JSON.stringify vs JSON.parse — The Complete Round-Trip
Every JSON data lifecycle follows the same pattern: serialise to cross a boundary, deserialise on the other side. Understanding both sides together is essential for writing bug-free data code.
JSON.stringify()Serialise
- → Object / Array / Value → JSON string
- → Escapes special characters
- → Omits undefined, functions, Symbols
- → Throws on circular refs and BigInt
- → Supports replacer + space params
- → Returns
undefinedfor non-serialisable top-level values
JSON.parse()Deserialise
- → JSON string → Object / Array / Value
- → Unescapes character sequences
- → Throws SyntaxError on invalid JSON
- → Dates become strings (not Date objects)
- → Supports reviver function to transform values
- → Always returns a value (never undefined)
// ── Full round-trip: Client → Server → Client ──────────────────
// 1. CLIENT: Stringify before sending
const payload = { userId: 4821, action: 'activate', meta: { source: 'dashboard' } };
const response = await fetch('/api/users/activate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload), // ← serialise
});
// 2. SERVER (Node.js/Express): Parse is automatic via express.json()
app.post('/api/users/activate', (req, res) => {
const { userId, action } = req.body; // ← already parsed by middleware
res.json({ ok: true, userId }); // ← express calls JSON.stringify() internally
});
// 3. CLIENT: Parse the response
const result = await response.json(); // ← implicitly calls JSON.parse()
console.log(result.ok); // true
// ── Reviver: Transform values during parse ──────────────────────
const data = JSON.parse(jsonString, (key, value) => {
// Convert ISO date strings back to Date objects
if (typeof value === 'string' && /^\d{4}-\d{2}-\d{2}T/.test(value)) {
return new Date(value);
}
return value;
});| Property | JSON.stringify() | JSON.parse() |
|---|---|---|
| Direction | Object → String | String → Object |
| Term | Serialisation / Encoding | Deserialisation / Decoding |
| Fails on | Circular refs, BigInt | Invalid JSON syntax |
| Lossy? | Yes (undefined, functions dropped) | No — all valid JSON types preserved |
| Second argument | replacer (filter/transform keys) | reviver (transform parsed values) |
| Third argument | space (indentation control) | None |
| Dates | Converted to ISO string | Returns string (not Date object) |
| Performance | O(n) — traverses all values | O(n) — parses all tokens |
Real-World JSON.stringify() Patterns
Beyond the basic use case, experienced JavaScript developers use JSON.stringify() in several powerful patterns. Here are the five most useful.
1. Deep clone an object (with caveats)
The fastest one-liner deep clone for serialisable objects
expand_more
1. Deep clone an object (with caveats)
The fastest one-liner deep clone for serialisable objects
// ✓ Works for objects with JSON-compatible values
const original = { user: { id: 1, prefs: { theme: 'dark' } } };
const clone = JSON.parse(JSON.stringify(original));
clone.user.prefs.theme = 'light'; // does NOT affect original
console.log(original.user.prefs.theme); // 'dark' — deep clone confirmed
// ✗ Limitations — these values are lost in the clone:
// - undefined properties (silently dropped)
// - Functions (dropped)
// - Date objects (become strings)
// - RegExp objects (become {})
// - Circular references (throw)
//
// For complex objects, use structuredClone() (modern browsers/Node 17+)
const betterClone = structuredClone(original);When to use: Quick deep clone for plain data objects (config, API responses, form state). Avoid for objects with Dates, functions, or circular refs — use structuredClone() instead.
2. Strip undefined values before sending to an API
JSON.stringify silently drops undefined — use it intentionally to clean payloads
expand_more
2. Strip undefined values before sending to an API
JSON.stringify silently drops undefined — use it intentionally to clean payloads
// API payload with optional fields
const updateUser = (id: number, changes: Partial<User>) => {
// undefined fields are automatically omitted from the JSON body
// — no need to manually delete them or use Object.fromEntries filter
return fetch(`/api/users/${id}`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
name: changes.name, // included only if not undefined
email: changes.email, // included only if not undefined
role: changes.role, // included only if not undefined
}),
});
};
// JSON.stringify({name: 'Alice', email: undefined, role: undefined})
// → '{"name":"Alice"}' — clean PATCH payloadWhen to use: PATCH requests where you only want to send changed fields. Construct an object with all possible keys, assign undefined to unchanged ones, and stringify — undefined keys are automatically omitted.
3. Omit sensitive fields with a replacer function
Use the replacer to block secrets from appearing in logs or API responses
expand_more
3. Omit sensitive fields with a replacer function
Use the replacer to block secrets from appearing in logs or API responses
const SENSITIVE_KEYS = new Set(['password', 'token', 'secret', 'apiKey', 'ssn']);
function safeStringify(obj: unknown): string {
return JSON.stringify(obj, (key, value) => {
if (SENSITIVE_KEYS.has(key)) return '[REDACTED]';
return value;
}, 2);
}
const user = {
id: 4821,
name: 'Alice Chen',
password: 's3cr3t!', // ← sensitive
token: 'jwt-abc-123', // ← sensitive
};
console.log(safeStringify(user));
// {
// "id": 4821,
// "name": "Alice Chen",
// "password": "[REDACTED]",
// "token": "[REDACTED]"
// }When to use: Logging objects that may contain credentials, tokens, or PII. The replacer runs recursively on nested objects — no need to strip keys manually at each level.
4. Detect object changes by comparing JSON strings
Stringify both versions and compare the strings — simple change detection for plain objects
expand_more
4. Detect object changes by comparing JSON strings
Stringify both versions and compare the strings — simple change detection for plain objects
const original = { name: 'Alice', role: 'viewer' };
const current = { name: 'Alice', role: 'admin' }; // role changed
const hasChanged = JSON.stringify(original) !== JSON.stringify(current);
console.log(hasChanged); // true
// ✓ Works for: flat objects, nested plain data, arrays
// ✗ Avoid for: objects with non-deterministic key order (use a
// canonical stringify library like json-stable-stringify instead)
// React: Detect if state actually changed before re-rendering
const prevRef = useRef(JSON.stringify(data));
useEffect(() => {
const current = JSON.stringify(data);
if (current !== prevRef.current) {
prevRef.current = current;
// only runs when data actually changed
}
}, [data]);Caveat: Key order in JavaScript objects is insertion-ordered in V8 but not guaranteed by spec for all cases. For reliable comparison, use json-stable-stringify which sorts keys alphabetically.
5. Force ASCII-safe output for older systems
Escape all non-ASCII characters to \uXXXX with a replacer — safe for any transport
expand_more
5. Force ASCII-safe output for older systems
Escape all non-ASCII characters to \uXXXX with a replacer — safe for any transport
function asciiSafeStringify(obj: unknown): string {
return JSON.stringify(obj, (_key, value) => {
if (typeof value === 'string') {
// Escape all non-ASCII characters to \uXXXX form
return value.replace(/[^\x00-\x7F]/g, (ch) => {
return '\\u' + ch.charCodeAt(0).toString(16).padStart(4, '0');
});
}
return value;
});
}
asciiSafeStringify({ greeting: 'héllo', name: '张伟', emoji: '🚀' });
// '{"greeting":"h\u00e9llo","name":"\u5f20\u4f1f","emoji":"\ud83d\ude80"}'
// — 100% ASCII, safe for any transport or legacy systemWhen to use: Environments that cannot handle UTF-8 (legacy APIs, certain CSV pipelines, systems that mangle multibyte characters). The output is still valid JSON — parsers handle \uXXXX sequences natively.
Stringifying in Other Languages
Every language with JSON support has an equivalent to JSON.stringify. The concept is the same: object → JSON string.
| Language | Stringify equivalent | Pretty-print variant |
|---|---|---|
| JavaScript | JSON.stringify(obj) | JSON.stringify(obj, null, 2) |
| Python | json.dumps(obj) | json.dumps(obj, indent=2) |
| Go | json.Marshal(obj) | json.MarshalIndent(obj, "", " ") |
| Java (Jackson) | mapper.writeValueAsString(obj) | mapper.writerWithDefaultPrettyPrinter()... |
| PHP | json_encode($obj) | json_encode($obj, JSON_PRETTY_PRINT) |
| C# (System.Text.Json) | JsonSerializer.Serialize(obj) | JsonSerializer.Serialize(obj, new JsonSerializerOptions { WriteIndented = true }) |
| Ruby | obj.to_json | JSON.pretty_generate(obj) |
Python — json.dumps()expand_more
import json
user = {"name": "Alice", "age": 30, "active": True}
# Compact (equivalent to JSON.stringify with no spaces)
compact = json.dumps(user, separators=(',', ':'))
# '{"name":"Alice","age":30,"active":true}'
# Pretty-printed
pretty = json.dumps(user, indent=2)
# {
# "name": "Alice",
# ...
# }
# Sort keys alphabetically
sorted_json = json.dumps(user, sort_keys=True)
# Ensure ASCII — escapes non-ASCII chars
ascii_safe = json.dumps(user, ensure_ascii=True)Go — json.Marshal()expand_more
package main
import (
"encoding/json"
"fmt"
)
type User struct {
Name string `json:"name"`
Age int `json:"age"`
Active bool `json:"active"`
}
func main() {
user := User{Name: "Alice", Age: 30, Active: true}
// Compact
b, _ := json.Marshal(user)
fmt.Println(string(b))
// {"name":"Alice","age":30,"active":true}
// Pretty-printed
b2, _ := json.MarshalIndent(user, "", " ")
fmt.Println(string(b2))
}C# (System.Text.Json)expand_more
using System.Text.Json;
var user = new { Name = "Alice", Age = 30, Active = true };
// Compact (default)
string compact = JsonSerializer.Serialize(user);
// {"Name":"Alice","Age":30,"Active":true}
// Pretty-printed
string pretty = JsonSerializer.Serialize(user,
new JsonSerializerOptions { WriteIndented = true });
// Newtonsoft.Json
using Newtonsoft.Json;
string njCompact = JsonConvert.SerializeObject(user);
string njPretty = JsonConvert.SerializeObject(user, Formatting.Indented);Double-Stringified JSON — JSON Inside JSON
Some APIs and event systems embed a JSON payload as a string value inside an outer JSON object. This requires double-stringification — stringifying a JSON string rather than an object.
{"event":"user.created","userId":4821}{
"type": "webhook",
"body": "{"event":"user.created","userId":4821}"
}The body field is a string that contains JSON — not an object. To produce it in JavaScript:
const inner = { event: 'user.created', userId: 4821 };
const outer = {
type: 'webhook',
body: JSON.stringify(inner), // stringify once → string value
};
JSON.stringify(outer); // stringify again → transmittable JSONThis pattern is common in AWS SQS/SNS messages, Stripe webhook events, Kafka message payloads, and any system where the transport envelope separates metadata from the data payload. Use this tool's Stringify mode to produce the inner string value, then paste it as the field value in your outer JSON.
When to Stringify JSON
Stringification is necessary whenever a JSON object must cross a boundary that only accepts plain strings — storage, transport headers, URL parameters, or nested JSON fields.
URL Query Parameters
APIs that accept filter or config JSON in query strings require it URL-encoded as a string. Stringify first, then encodeURIComponent().
localStorage & Cookies
Browsers only store strings in localStorage and cookies. JSON.stringify converts your object to a storable string; JSON.parse reads it back.
HTTP Request Bodies
fetch() body must be a string. JSON.stringify converts your object to a valid application/json body for POST, PUT, and PATCH requests.
JSON Field Values
Some APIs embed a JSON payload as a string field inside an outer JSON envelope. Stringify produces the correctly escaped inner string.
Shell & CLI Arguments
Passing JSON to a CLI tool or shell command requires a single-string form. Stringify gives the correctly escaped compact representation.
Logging & Debugging
console.log(obj) shows [object Object] in some environments. JSON.stringify ensures the full structure is captured as readable text.
Stringify vs Parse vs Formatter
All three deal with JSON — but they serve opposite purposes in the data lifecycle.
| Feature | JSON Stringify | JSON Parser | JSON Formatter |
|---|---|---|---|
| Operation | Serialisation | Deserialisation | Reformatting |
| Direction | Object → String | String → Object | JSON → JSON |
| Output | Escaped string literal | Structured data + stats | Indented valid JSON |
| Escapes characters | ✓ Yes | ✗ No | ✗ No |
| Shows parse stats | ✗ No | ✓ Type, keys, depth | ✗ No |
| Changes JSON data | ✗ No | ✗ No | ✗ No |
| Best for | Sending & storing JSON | Reading & analysing JSON | Making JSON readable |
JSON Has Errors? Validate First
Stringify requires valid JSON input. If the operation fails, use the JSON Validator to locate the exact syntax error, or the JSON Parser for a full structural breakdown.
Frequently Asked Questions
What does JSON.stringify() do?
expand_more
JSON.stringify() converts a JavaScript object, array, or value into a JSON-formatted string. It serialises in-memory data into portable text that can be stored, transmitted, or embedded. The output is a string enclosed in double quotes with all internal special characters escaped.
What is the difference between JSON.stringify and JSON.parse?
expand_more
JSON.stringify converts an object into a JSON string (serialisation). JSON.parse converts a JSON string back into an object (deserialisation). They are exact inverses — stringify to send or store data, parse to receive and use it.
What characters does JSON.stringify escape?
expand_more
JSON.stringify escapes double quotes as \", backslashes as \\, newlines as \n, carriage returns as \r, tabs as \t, and all other ASCII control characters (U+0000–U+001F) as \uXXXX Unicode escapes.
What happens to undefined, functions, and Symbols when stringifying?
expand_more
Object properties with undefined values are silently omitted. Functions and Symbol-keyed properties are also skipped. If the top-level value passed to JSON.stringify is undefined or a function, the return value is undefined (not a string).
What does the space parameter do in JSON.stringify?
expand_more
The third argument controls indentation: JSON.stringify(obj, null, 2) produces 2-space pretty-printed output. JSON.stringify(obj, null, "\t") uses tabs. Omitting the argument (or passing 0 or null) produces compact, minified output — identical to JSON minification.
What is the replacer parameter in JSON.stringify?
expand_more
The second argument is the replacer. Pass an array of key names to act as an allowlist (only those keys are included), or a function that receives each key-value pair and returns the value to include — returning undefined omits the key.
What happens with circular references?
expand_more
JSON.stringify throws a TypeError: "Converting circular structure to JSON" for objects with circular references. Use a library like flatted or fast-safe-stringify, or write a replacer function that tracks seen objects and replaces cycles with a placeholder.
What is double-stringified JSON?
expand_more
Double-stringified JSON occurs when JSON.stringify is applied to an already-valid JSON string, producing a string-within-a-string: "{\"name\":\"Alice\"}". This pattern is used in APIs (AWS SQS, Stripe webhooks) that embed a JSON payload as a string field inside an outer JSON envelope.
When would I need to stringify JSON?
expand_more
You need stringify when embedding JSON in a URL query parameter, storing an object in localStorage or a cookie, writing a fetch() request body, embedding a JSON payload as a string value inside another JSON field, or ensuring objects are logged as readable text rather than [object Object].
Is this JSON stringify tool free?
expand_more
Completely free with no account required. All processing runs locally in your browser — no data is uploaded to any server.
About This Tool
Built by OpenFormatter · Last updated
Part of the JSON Toolkit
Explore All JSON Tools
Free online tools for every JSON task — format, validate, convert, compare, and more.