toJSON() is how JavaScript Date objects become JSON-safe strings. It powers automatic date conversion in JSON.stringify and returns the same UTC ISO format as toISOString(). This guide covers syntax, stringify behavior, round-trip parsing, and error handling.
01
Syntax
toJSON()
02
stringify
Auto-called
03
ISO 8601
UTC output
04
parse
Round-trip
05
APIs
Payloads
06
Invalid
RangeError
Fundamentals
Introduction
JSON cannot store real Date objects—only strings, numbers, booleans, arrays, and plain objects. When you save or send dates over HTTP, you need a reliable text format. toJSON() bridges that gap by converting a Date into a portable UTC ISO string.
You rarely need to call it manually: JSON.stringify invokes toJSON() on every value that defines it. For dates, the result matches toISOString(). To read values back, pair with Date.parse() or the new Date(isoString) constructor after JSON.parse.
Concept
Understanding the toJSON() Method
Date.prototype.toJSON() exists specifically for JSON serialization. The built-in implementation returns this.toISOString(), producing strings like 2026-03-15T12:30:45.500Z.
Explicit call — date.toJSON() returns the ISO string directly.
Automatic call — JSON.stringify({ createdAt: date }) calls toJSON() on the Date while building JSON.
Read-only — the original Date object is not modified.
Invalid dates — throw RangeError, which also breaks JSON.stringify on that value.
💡
Beginner Tip
These two lines produce the same JSON text for a date field: JSON.stringify({ at: new Date() }) and JSON.stringify({ at: new Date().toJSON() }). The first lets stringify call toJSON() for you.
Foundation
📝 Syntax
JavaScript
dateObj.toJSON()
Parameters
None. (The JSON spec allows a key argument when stringify calls toJSON; Date ignores it.)
Return value
A UTC ISO 8601 string—the same output as toISOString() for valid dates.
Throws RangeError: Invalid time value if the Date is invalid.
Cheat Sheet
⚡ Quick Reference
Goal
Code
Explicit JSON string from Date
date.toJSON()
Serialize object with dates
JSON.stringify(obj)
Same as ISO formatter
date.toISOString()
Parse JSON back to Date
new Date(parsed.createdAt)
Validate before serialize
Number.isNaN(date.getTime())
Store epoch number instead
date.getTime()
Compare
📋 toJSON() vs Similar Approaches
Choose the path that matches how your data travels—JSON text, ISO strings, or numeric timestamps.
toJSON()
JSON path
stringify hook
toISOString()
UTC ISO
Same output
getTime()
epoch ms
Numeric JSON
Date.parse()
string→ms
Read pair
Hands-On
Examples Gallery
Open DevTools Console (F12) or use Try-it links. Fixed examples use Date.UTC() for predictable UTC output.
📚 Getting Started
Call toJSON() directly and see the ISO string it returns.
Example 1 — Basic toJSON() Output
March 15, 2026 at 12:00 UTC serializes as a standard ISO string.
JavaScript
const date = new Date(Date.UTC(2026, 2, 15, 12, 0, 0));
const jsonDate = date.toJSON();
console.log(jsonDate); // "2026-03-15T12:00:00.000Z"
While walking the object tree, JSON.stringify detects the Date’s toJSON method and uses its return value. That is why API clients see ISO strings, not {} or locale text.
Example 3 — Compare toJSON() and toISOString()
For built-in Date objects, both methods return identical strings.
JavaScript
const date = new Date(Date.UTC(2026, 2, 15, 12, 0, 0));
console.log(date.toJSON()); // JSON hook
console.log(date.toISOString()); // explicit ISO
console.log(date.toJSON() === date.toISOString()); // true
Use toISOString() when you want an ISO string outside JSON. Use toJSON() when documenting stringify behavior—or call either; the output is the same for Date.
Example 4 — Round-Trip: Serialize, Parse, Reconstruct
Send a user record as JSON and rebuild the Date on the other side.
JavaScript
const user = {
name: "John Doe",
birthdate: new Date(Date.UTC(1990, 4, 20))
};
const json = JSON.stringify(user);
const parsed = JSON.parse(json);
const restored = new Date(parsed.birthdate);
console.log(json);
console.log(restored.toJSON()); // same instant as original
After JSON.parse, date fields are plain strings. Pass them to new Date() or Date.parse() to recover a Date object with the same instant.
Example 5 — Guard Before Serializing Invalid Dates
Invalid dates throw when toJSON() runs—including inside JSON.stringify.
JavaScript
const bad = new Date("not-a-date");
if (Number.isNaN(bad.getTime())) {
console.log("Skip invalid date in JSON payload");
} else {
console.log(JSON.stringify({ at: bad }));
}
Without the guard, JSON.stringify({ at: bad }) throws RangeError: Invalid time value when stringify reaches the Date’s toJSON() call.
Applications
🚀 Common Use Cases
REST API bodies — fetch with JSON.stringify converts Date fields automatically.
localStorage / sessionStorage — persist objects with date properties as JSON text.
Database JSON columns — store ISO strings produced by toJSON().
Logging pipelines — structured logs with ISO timestamps in JSON lines.
Unit tests — assert JSON.stringify(model) contains expected ISO values.
Microservice messages — event envelopes with occurredAt as portable UTC text.
🧠 How toJSON() Fits Into JSON Serialization
1
stringify walks value
JSON.stringify visits each property in your object.
stringify
2
Detect toJSON
If a value has toJSON, stringify calls it instead of default Date formatting.
toJSON
3
Date returns ISO
Built-in Date toJSON delegates to toISOString() for UTC output.
ISO
4
📦
JSON text emitted
The ISO string is quoted in JSON—ready for HTTP, files, or databases.
Important
📝 Notes
toJSON() output equals toISOString() for standard Date objects.
Read-only: does not mutate the Date.
JSON.stringify on an array of dates converts each element via toJSON().
After JSON.parse, date fields are strings—wrap with new Date() to use Date methods again.
Invalid dates throw RangeError—validate before stringify in production code.
For numeric JSON timestamps, store getTime() instead of relying on toJSON().
Compatibility
Browser & Runtime Support
Date.prototype.toJSON() has been available since ES5 alongside JSON.stringify. It works in every modern browser and Node.js.
✓ Baseline · ES5
Date.prototype.toJSON()
Supported in Chrome, Firefox, Safari, Edge, Internet Explorer 8+, and all Node.js versions. No polyfill required.
99%Universal API
Google ChromeSupported · Desktop & Mobile
Full support
Mozilla FirefoxSupported · Desktop & Mobile
Full support
Apple SafariSupported · macOS & iOS
Full support
Microsoft EdgeSupported · Chromium
Full support
Internet ExplorerNo native support · Use a polyfill
Polyfill
OperaSupported · Modern versions
Full support
Samsung InternetSupported · Android
Full support
BunSupported · JavaScript runtime
Supported
DenoSupported · JavaScript runtime
Supported
Node.jsSupported · Server runtime
Supported
Android WebViewSupported · Modern WebView
Full support
Date.toJSON()Excellent
Bottom line: Safe everywhere. Remember stringify calls it automatically, output matches ISO, and invalid dates throw.
Wrap Up
Conclusion
toJSON() is the bridge between JavaScript Date objects and JSON text. Whether you call it explicitly or let JSON.stringify invoke it, you get portable UTC ISO strings ideal for APIs and storage.
Next, learn toLocaleDateString() for human-facing locale formatting, or review toISOString() for the ISO formatter that powers toJSON() under the hood.
Your foundation for serializing dates in JSON workflows.
5
Core concepts
📝01
Syntax
toJSON()
API
📦02
stringify
Auto hook.
JSON
📋03
ISO match
= toISOString.
Format
🔄04
Round-trip
parse + new Date.
Restore
⚠05
Invalid
RangeError.
Guard
❓ Frequently Asked Questions
For valid Date objects, the same UTC ISO 8601 string as toISOString() — for example, "2026-03-15T12:00:00.000Z". It is designed for JSON serialization, not for human display.
JSON.stringify() calls toJSON() on any value that has the method while building JSON text. That is why Date objects inside objects and arrays become ISO strings in JSON output.
Yes. The built-in Date implementation of toJSON() returns this.toISOString(). You can call either explicitly; stringify uses toJSON() under the hood.
Pass the object to JSON.stringify. Date properties are converted via toJSON() automatically. You can also assign date.toJSON() or date.toISOString() to a string field before stringify if you want explicit control.
After JSON.parse, pass the ISO string to new Date(isoString) or Date.parse(isoString). Both accept the format produced by toJSON().
It throws RangeError: Invalid time value — the same as toISOString(). Validate with Number.isNaN(date.getTime()) before serializing.
Did you know?
Custom classes can define their own toJSON() method to control exactly what JSON.stringify emits—Date’s built-in version is why dates never appear as empty objects in JSON output.