Reputation: 223
I've got some data represented as an object of class X. Some fields of that object contain dates - instances of the standard built-in Date
constructor.
The thing is that I need to pass that object of class X as a JSON string using Axios. And when the fields representing dates are converted to strings, the Date.prototype.toISOString
is used on them. However, it converts the strings to the following format: 2017-11-14T06:22:43.000Z
, - while I need them to be almost the same, but without this .000Z
at the end (the server seems to dislike that).
I see 2 options how can I achieve that:
Date.prototype.toISOString
methodsubstr
: there occurs an endless recursion. Look:Date.prototype.toISOString = function(...args) {
const res = Date.prototype.toISOString(...args);
return res.substr(0, 19);
};
const date = new Date();
document.write(date.toISOString());
The following way it doesn't work as well:
const originalMethod = Date.prototype.toISOString;
Date.prototype.toISOString = function(...args) {
const res = originalMethod(...args);
return res.substr(0, 19);
};
const date = new Date();
document.write(date.toISOString());
See the console. It outputs "Method Date.prototype.toISOString called on incompatible receiver undefined"
So, why doesn't that work? And, more importantly, what would be the best way of solving my problem?
Upvotes: 0
Views: 1111
Reputation: 29010
You can create your own replacer function to be used with JSON.stringify()
. You can add special handling for any dates but leave any other value intact:
function customReplacer(key, value) {
if (key === "") //initial object
return value;
if (this[key] instanceof Date) //any date
return value.slice(0, 19);
return value; //anything else
}
const obj = {
a: "hello world",
b: {
c: 42
},
d: [1, 2, 3],
e: new Date(),
f: {
g: true,
h: new Date(),
i: null
}
}
console.log(JSON.stringify(obj, customReplacer, 4))
.as-console-wrapper {
max-height: 100% !important;
}
Note that value
is going to be the serialised value, not a Date object. Hence, to get the initial non-serialised object, you need to get this[key]
- the function is going to be called with the object that's currently serialised as this
.
Upvotes: 1
Reputation: 664599
why doesn't that work?
Because you're calling the originalMethod
without a this
value. A working code would be
const originalMethod = Date.prototype.toISOString;
Date.prototype.toISOString = function(...args) {
const res = originalMethod.apply(this, args);
return res.substr(0, 19);
};
I don't know if it's a good decision
No, definitely not. Do not mess with builtins - other parts of your code (or its dependencies) might rely on their correct functioning.
What would be the best way of solving my problem?
Don't modify the toJSON
behaviour of all Date
instances, modify the serialisation of your X
objects only:
class X {
…
toJSON() {
return {
...this,
// TODO: fix backend to acccept standard timestamp formats
date: this.date.toISOString().replace(/(?:\.\d{1,3})?Z$/, ''),
…
};
}
}
Upvotes: 2