JSON Serialization of Dates (Take 2)

JavaScript doesn't have a nice literal syntax for date values, which results in some complications in JSON serialization. This post describes the approach we adopted to enable serialization of date values...

A while back I blogged about the what I thought was oddly lacking from JavaScript - a literal syntax for Date objects, and proposed a Date literal syntax such as @11/14/2006 11:12:02 AM@, while admitting it was wishful thinking, since it was unlikely it would happen anytime soon, and even if it did, wouldn't be something that could be depended on for a number of years until it became ubiquitous enough.

In response to yesterday's post about the Web Development Helper, and its new JSON viewer, there was a comment about the tool not understanding something like new Date(...) in the JSON content. That is true, and by design. The tool only parses true JSON, also sometimes referred to as safe JSON, which is a subset of JavaScript that only uses literal syntax for primitives, objects, and arrays. The tool doesn’t attempt to parse arbitrary JavaScript, not even expressions such as new.

So what about Dates? They are certainly still just as interesting from a serialization perspective. At the same time, we wanted to specifically ensure our serialization format adhered to the actual definition of the JSON syntax. Since I blogged about the @-based syntax, we went ahead and implemented it (in both ASP.NET Ajax and Script#). Actually we implemented a slightly different version, so it wouldn’t require any new JavaScript syntax. We specifically serialize the syntax above as a string with some easily identifiable markers. So say I had an object with a currentDate property. That would get serialized as:

    { currentDate: "@1163531522089@" }
The string has to begin and end with "@". The number in between the @ characters is the number of milliseconds since Jan 1st 1970 (which is what we can get from JavaScript) in the normalized UTC equivalent.

On the server, the JSON parser looks for the special string, and knows to construct a CLR DateTime object. On the client, we have a bit of regex that easily turns this into an equivalent new Date(...) before we call eval to perform the actual JSON deserialization.


[ Tags: | | | ]
Posted on Tuesday, 11/14/2006 @ 12:46 PM | #Ajax


Comments

21 comments have been posted.

LovedJohnySmith

Posted on 11/14/2006 @ 7:41 PM
Hi Nikhil,

Is it possible to use json library in Infopath rendering. As we know, Json is a light weight protocol, i just wonder if we can able to use json library with infopath.

Please update me.

daniel

Posted on 11/15/2006 @ 5:14 AM
Hi Nikhil,
I'm working with Java script serialization quite some time now and recently i found out about .toSource() API in Mozilla (quite similar to JSON).
it addresses date and circular reference issues.
what's your take on that ?
why not use that approach as the standard, and develop JS library for I.E. computability (there are some out there).
you can find an example here :
http://eventhandler.blogspot.com/2006/10/native-object-serialization-in.html

Daniel.

Alex Osipov

Posted on 11/15/2006 @ 9:01 AM
Hi Nikhil,

I think the JSON viewer doesn't actually conform to true JSON spec as it parses single quotes as string delimeters, while JSON spec specifiies only double quote character. But please don't fix this ;)

AO

Nikhil Kothari

Posted on 11/15/2006 @ 10:52 AM
LovedJohnySmith: The serialization logic is just some JavaScript code - assuming InfoPath allows you to include a script file, and write script code, you should definitely be able to plug this in into your scenario. I've never worked with InfoPath at that level of detail to be able to answer how or more specifically.

Daniel: toSource only exists on Mozilla. Furthermore toSource uses new Date(...) in what it generates, which isn't part of the JSON spec.

Alex: OK... I meant follows the spec in a loose sense. In addition to supporting single quotes, it also supports unquoted field names on objects. Yes, support for those won't be removed. :-)

Hannes Preishuber

Posted on 11/16/2006 @ 12:36 AM
as i have written in my blog, regex is not the fastest way and is made to the whole string and not only to the date part
http://weblogs.asp.net/hpreishuber/archive/2006/10/29/ASP.NET-AJAX-JSON-Date-serialization.aspx

Nikhil Kothari

Posted on 11/16/2006 @ 3:26 AM
Actually the regex isn't too bad of an approach unless you're sending down huge amounts of JSON in each request, in which case you've probably got some other problems to deal with. Furthermore, if you don't keep creating new regex's but use a single one the engine compiles the regex the first time around.

TingLi

Posted on 11/16/2006 @ 6:08 AM
Hi Nikhil,
Your website looks pretty good. You do it by yourself or by the template ?
Hope your response.

Ron Buckton

Posted on 11/17/2006 @ 6:03 PM
Why not use a "date literal" format that can still be JSON evaluated, e.g.

function $D(value) {
if (String.isInstanceOfType(value)) {
return Date.parse(value);
}
else if (Number.isInstanceOfType(value)) {
return new Date(value);
}
}


var o = eval("{ name : 'foo', date : $D(1163531522089) }");

The $D would be as easy to parse on the server as @@ and doesn't require the regex on the client, which reduces deserialization cost and keeps it in-line with regular JSON.

Nikhil Kothari

Posted on 11/17/2006 @ 11:30 PM
The driving goal is not ease of parsing on the server. Whats driving the approach is the requirement to only have data in the format (which is the definition of "regular JSON" if you look at the space) ... so no calls to javascript code, no dependence on particular script code/framework etc.

Stephen McKamey

Posted on 11/20/2006 @ 4:36 PM
The reference implementation of JSON encodes dates as ISO-8601 strings (as of 2006-11-09): http://json.org/json.js
You could use that format and then it would be consistent without introducing a new syntax.

Nikhil Kothari

Posted on 11/21/2006 @ 12:19 PM
Stephen, I have no idea what you are referring to. JavaScript does not have a date literal syntax, which is what is needed here. In the absense of it you need to encode dates as strings, but still be able to distinguish it as a date as opposed to an arbitrary string.

Also the site you link to has no reference to dates.

Thomas S. Trias

Posted on 12/21/2006 @ 2:53 PM
Nikhil, Stephen is referring to the toJSONString serialization added to the Date class by json.js; it uses ISO-8601 serialization (although it doesn't like years before 1000 or after 9999).

Nikhil Kothari

Posted on 12/29/2006 @ 11:17 AM
Thomas, thanks for pointing out. I was looking on the page itself... I didn't download the script. Anyway, it seems it is just another way of doing things. Now that I do see what its doing, I am not sure its helpful or usable - it doesn't have any mechanism in place to distinguish between a Date and a String that happens to look like a date.

lexp

Posted on 1/3/2007 @ 9:17 PM
Nikhilk, if date is encoded using @...@ syntax, how '@' character is encoded in strings?

Nikhil Kothari

Posted on 1/5/2007 @ 9:05 AM
Actually I've updated Dates to be encoded as "\@...@". Keep in mind the regex literally looks for quote\@[digits]@quote. If a string also is \@...@, it will get serialized with quote escaped... and this will not match the regex.

GLM

Posted on 1/12/2007 @ 10:27 AM
Interesting behavior having the milliseconds rather than the mm-dd-yyyy serialized.
The thing here is that if the browser has a diferent time zone than the server it will render another time when calling alert(dateTime);
I know it makes sense: in a distributed application the user will like to know when an event happend based on his local time but anyway,
How am I supposed to avoid this?

Nikhil Kothari

Posted on 1/26/2007 @ 12:33 AM
As mentioned in the post, this uses the UTC time to avoid issues resulting from differing time zones...

SHH

Posted on 4/5/2007 @ 3:02 PM
I was looking at your response to lexp about \@..@ in string values.
Say, for some reason, we have a string value of \@-59995710000@ that needs to be Json-ized and a date of 6 Feb 1968 at 06:31:30 that needs to be Json-ized.
Both result in exactly the same Json value, "\@-59995710000@". Your regex will think the string is a date and convert it, is this not true?
Would it not be better to use a non-quoted literal for dates, just @-59995710000@, similar to how booleans are handled? It would not be "regular Json" by the definition of json.org, but aren't you attempting to alter the definition of Json to include a literal format for dates?

Zarko

Posted on 5/10/2007 @ 12:35 PM
Seems to me like this is going in a wrong direction - trying to be 100% compliant with an RFC which is far from being complete and then breaking the core principle behind the JSON (has to be JavaScript object definition).

I'd say that it would be much more reasonable, to simply go back to the root -- ECMA-262, and add the minimal type declaration -- even if it has to be spelled out as new Date(...).

With that, UI folks will be able to continue using it as if nothing happened, but we'll also have a solid base to have a real serialization, kick SOAP out of the way for web services and not having to lose type safety. A lot of good things from a lil new date(...) I'd say :-). I'm pretty sure that Doug would consider the minimal addition to the RFC 4627 as long as it is honestly minimal (as in no IBM dumping their 32+ XSD 'types').

Ryan Connelly

Posted on 5/31/2007 @ 4:21 PM
I've come across an interesting issue. I've got a web app (same exact code and asp.net ajax libraries) running on vista and win 2k3. Ajax calls with DateTime params are failing on the vista's IIS 7 (Error: @1178035200000@ is not a valid value for DateTime). It works perfectly on the 2k3 (with IIS 6.0). Is there something that changed for .net 2.0 on vista or IIS 7.0? Has anyone else had this issue?

Also, are there plans to move away from the @ based date literal?

__________

Posted on 5/29/2009 @ 3:15 AM
ghfghfghgfh
Post your comment and continue the discussion.