I have JS objects that I need to stringify (to insert into Postgres). These objects contain Date
s, which need to be saved as timestamps rather than ISO representations.
In the context our my application, this is most conveniently done via a JSON.stringify
replacer function (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#syntax).
However, Date
behaves very weirdly in there. Consider:
function replacer(key, value) {
if (key != "temp") {
return value
}
console.log(`[${key}]=${value}`)
let areWeObjectivelyDating = this[key] instanceof Date
let areWeSubjectivelyDating = value instanceof Date
console.log("are we dating?")
if (areWeObjectivelyDating) {
console.log("> it's a date!")
}
else {
console.log("> objectively, no")
}
if (areWeSubjectivelyDating) {
console.log("> from my perspective? yes!")
}
else {
console.log("> sorry I don't see us working out")
}
console.log()
return value
}
let json = {
temp: new Date()
}
console.log("= check replacer solo =")
replacer("temp", json["temp"])
console.log("")
console.log("= check replacer in stringify =")
JSON.stringify(json, replacer)
The output is:
= check replacer solo =
[temp]=Wed Jun 26 2024 09:20:53 GMT+0000 (Coordinated Universal Time)
are we dating?
> objectively, no
> from my perspective? yes!
= check replacer in stringify =
[temp]=2024-06-26T09:20:53.371Z
are we dating?
> it's a date!
> sorry I don't see us working out
The solo check works as expected. But when replacer
is called by JSON.stringify
, I can access json["temp"]
via this
, which gives me the actual Date
object. However, value
is the date already converted to an ISO string.
Why is this the case? Where is this (unexpected) behavior documented?
As usual, this is already answered:
What does instanceof behave differently inside JSON.stringify()?
In short: Date
has a toJSON
method which serializes before the value is passed to the replacer.