Deserializing JSON Strings as JavaScript Date Objects
JSON is a very lightweight data-interchange format that only supports a handful of values:
- objects
- arrays
- strings
- numbers
true
andfalse
null
Note that there's no special type for datetimes defined in the JSON grammar. Therefore, datetimes are usually represented as strings that adhere to a specific format like ISO-8601:
{
"date": "2016-04-26T18:09:16Z"
}
Now imagine you're making an API call that returns the above JSON in the body of the HTTP response. Generally, you'd use the JSON.parse()
function to deserialize the string into a JavaScript object:
const body = `{
"date": "2016-04-26T18:09:16Z"
}`;
const obj = JSON.parse(body);
However, the obj.date
property is not a Date
object, but a simple string. After all, there's no magic involved that causes JSON.parse()
to deserialize certain string values as dates:
const { date } = obj;
console.log(typeof date);
// "string"
It might be desirable in some cases to establish the convention that values which look like dates are automatically deserialized as such, the premise being that further processing is simpler if a datetime is represented by an actual Date
instance rather than a plain string.
To establish that convention, you can pass a function as the second argument to the JSON.parse()
call which allows you to transform the value originally parsed before returning it. JSON.parse()
calls that function with the current key and value:
const dateFormat = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/;
function reviver(key, value) {
if (typeof value === "string" && dateFormat.test(value)) {
return new Date(value);
}
return value;
}
const text = '{ "date": "2016-04-26T18:09:16Z" }';
const obj = JSON.parse(text, reviver);
console.log(typeof obj.date);
// "object"
Here, we're parsing a JSON object with a single date
property that holds a date which is expressed as a string according to ISO 8601, a standard describing the representation of dates and times. Now, the obj.date
property is an instance of Date
, so the typeof
operator returns "object"
.
Of course, you're free to use whatever mechanism you want to detect datetime values. The specific regular expression pattern generally depends on how the backend(s) you're talking to deserialize(s) datetime values. However, you might also decide to inspect the key
parameter to decide whether or not to create a Date
instance from a given value. It's totally up to you!
Finally, please be aware that this approach isn't bulletproof in all cases, especially not with freeform user input. A string value that looks like a date but doesn't actually represent one is a false positive. Therefore, be as restrictive as possible when specifying the target datetime string format.