2

我正在使用 JSON Web 服务的 HTML5/JavaScript 中构建一个 Windows 8 Metro 应用程序(又名“现代 UI 样式”或“Windows 商店应用程序”),我遇到了以下问题:我的 JSON Web 服务应该以哪种格式序列化Windows 8 Metro JSON.parse方法的日期以反序列化日期类型中的日期?

我试过:

  • 使用ISO-8601 格式发送日期,(JSON.parse 返回一个字符串),
  • 发送日期,如“/Date(1198908717056)/”,如此处所述(结果相同)。

我开始怀疑 Windows 8 的 JSON.parse 方法是否支持日期,因为即使解析其自己的 JSON.stringify 方法的输出也不返回日期类型。

例子:

    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"
4

2 回答 2

4

以下是我如何以通用方式实现此功能(尽管我宁愿找到 Windows 8 的 JSON.parse 方法支持的开箱即用格式):

在服务器上,我正在使用以下命令序列化我的字符串:

date1.ToString("s");

这使用始终相同的 ISO 8601 日期格式,无论使用何种文化或提供的格式提供程序(有关更多信息,请参见此处)。

在客户端,我为 JSON.parse 指定了一个“reviver”回调,它使用正则表达式查找日期并将它们自动转换为日期对象。

最后,反序列化的对象将包含实际的 JavaScript 日期类型,而不是字符串。

这是一个代码示例:

    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]));
    }
});

希望这会有所帮助,卡尔

于 2012-09-10T15:40:22.507 回答
2

这不是 Windows 8 独有的JSON.parse——它是ECMA 标准 JSON 解析器的设计行为。因此,日期没有(并且可能)没有“开箱即用的支持”。

根据规范,JSON 值只能是字符串、数字、布尔值、数组、对象或null. 不支持日期。 (IMO,这是对规范的疏忽,但这是我们必须忍受的。)

由于没有日期类型,您的应用程序必须自己解决如何处理日期。处理此问题的最佳方法是将日期发送为 ISO 8601 字符串 (yyyy-MM-dd'T'HH:mm:ss'Z') 或自纪元以来的毫秒数(1970 年 1 月 1 日 00:00:00 UTC)。这里的重要部分是确保时间是 UTC。

如果性能很重要,我不会使用带有JSON.parse. 我做了很多测试,为对象中的每个属性调用函数所涉及的开销将性能降低了一半

另一方面,我真的很惊讶针对每个字符串值测试正则表达式与仅解析已知属性名称相比的效果如何。只需确保在循环之外定义一次正则表达式!

显然,将 JSON 值转换为日期的绝对最快的方法是,如果您确切知道需要为日期解析哪些属性。但是,鉴于基于正则表达式的搜索方法的出色性能,我认为不值得额外的复杂性,除非您真的需要额外的性能。

关于使用 ISO 字符串与自纪元以来的毫秒数的说明:独立测试,毫秒胜出。在 IE 中,没有区别,但 Firefox 似乎确实在处理 ISO 字符串。另请注意,Date构造函数在所有浏览器中都需要毫秒。它也需要一个 ISO 字符串,但不是 IE ≤ 8。

于 2012-09-10T18:20:52.427 回答