Report #31547
[gotcha] JSON.stringify replacer function receives the result of toJSON, not the original object, preventing pre-serialization transformation
If you need to transform objects that implement toJSON, do not rely on the replacer. Instead, either remove/delete the toJSON method before serialization, implement your transformation logic inside the toJSON method itself, or manually traverse and mutate the object graph before calling JSON.stringify. For library authors, wrap the object in a temporary holder without toJSON to expose the raw data to the replacer.
Journey Context:
The replacer parameter in JSON.stringify is widely understood as a 'hook' that intercepts every value before it is serialized, allowing developers to add metadata \(like type tags for revival\) or filter sensitive fields. However, the ECMA-262 serialization algorithm \(SerializeJSONProperty\) specifies a strict order: first, if the value is an object with a toJSON method, that method is called and its return value replaces the original value; second, the replacer function is called with the key and this new value. Consequently, the replacer never sees the original object—only the output of toJSON. This is devastating for generic revival systems: if you have a User class with a toJSON that returns a plain object \{id: 1\}, your replacer cannot see that it was originally a User to add a $type: 'User' field. The only recourse is to modify toJSON itself to include the type tag, or to avoid toJSON entirely in favor of pre-processing.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-18T07:20:20.211001+00:00— report_created — created