How to deserialize JSON text into a date type using Windows 8 JSON.parse?

好久不见. 提交于 2019-12-08 01:52:48

问题


I'm building a Windows 8 Metro app (aka "Modern UI Style" or "Windows Store app") in HTML5/JavaScript consuming JSON Web Services and I'm bumping into the following issue: in which format should my JSON Web Services serialize dates for the Windows 8 Metro JSON.parse method to deserialize those in a date type?

I tried:

  • sending dates using the ISO-8601 format, (JSON.parse returns a string),
  • sending dates such as "/Date(1198908717056)/" as explained here (same result).

I'm starting to doubt that Windows 8's JSON.parse method supports dates as even when parsing the output of its own JSON.stringify method does not return a date type.

Example:

    var d = new Date(); // => a new date
    var str = JSON.stringify(d); // str is a string => "\"2012-07-10T14:44:00.000Z\""
    var date2 = JSON.parse(str); // date2 is a string => "2012-07-10T14:44:00.000Z"

回答1:


Here's how I got this working in a generic way (though it I'd rather find a format supported out-of-the-box by Windows 8's JSON.parse method):

On the server, I'm serializing my strings using:

date1.ToString("s");

This uses the ISO 8601 date format which is always the same, regardless of the culture used or the format provider supplied (see here for more information).

On the client-side, I specified a "reviver" callback to JSON.parse which looks for dates using a regexp and converts them into a date object automatically.

In the end, the deserialized object will contain actual JavaScript date types and not strings.

Here's a code sample:

    var responseResult = JSON.parse(request.responseText, function dateReviver(key, value) {
if (typeof value === 'string') {
    var re = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)$/
    var result = re.exec(value);
    if (result) {
        return new Date(Date.UTC(+result[1], +result[2] - 1, +result[3], +result[4],+result[5], +result[6]));
    }
});

Hope this helps, Carl




回答2:


This is not something that's unique to Windows 8's JSON.parse – it's the by-design behavior of the ECMA standard JSON parser. Therefore, there is (and can be) no "out-of-the-box support" for dates.

Per spec, JSON values can only be a String, Number, Boolean, Array, Object, or null. Dates are not supported. (IMO, this is an oversight on the part of the spec, but it's what we have to live with.)

Since there is no date type, your app has to work out how to handle dates on its own. The best way to handle this is to send dates as ISO 8601 strings (yyyy-MM-dd'T'HH:mm:ss'Z') or as milliseconds since the epoch (Jan 1 1970 00:00:00 UTC). The important part here is to make sure time is in UTC.

If performance is important, I would not use a reviver callback with JSON.parse. I did a lot of testing, and the overhead involved with invoking a function for every single property in your object cuts performance in half.

On the other hand, I was honestly surprised with how well testing a regex against every string value stood up against only parsing known property names. Just make sure you define the regex once, outside the loop!

Obviously, the absolute fastest ways to turn JSON values into Dates is if you know exactly what properties need to be parsed for dates. However, given the surprisingly good performance of the regex-based search methods, I don't think it's worth the extra complexity unless you really need the extra performance.

A note on using ISO strings vs milliseconds since epoch: tested independently, milliseconds wins. In IE, there's no difference, but Firefox really seems to struggle with ISO strings. Also note that the Date constructor takes milliseconds in all browsers. It also takes a the ISO string, but not in IE ≤ 8.



来源:https://stackoverflow.com/questions/12354702/how-to-deserialize-json-text-into-a-date-type-using-windows-8-json-parse

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!