惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Apple Machine Learning Research
Apple Machine Learning Research
M
MIT News - Artificial intelligence
罗磊的独立博客
博客园 - 【当耐特】
A
About on SuperTechFans
Last Week in AI
Last Week in AI
雷峰网
雷峰网
IT之家
IT之家
aimingoo的专栏
aimingoo的专栏
H
Hackread – Cybersecurity News, Data Breaches, AI and More
博客园_首页
博客园 - 叶小钗
Microsoft Azure Blog
Microsoft Azure Blog
博客园 - Franky
J
Java Code Geeks
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
D
Docker
Engineering at Meta
Engineering at Meta
B
Blog RSS Feed
The Cloudflare Blog
大猫的无限游戏
大猫的无限游戏
阮一峰的网络日志
阮一峰的网络日志
S
SegmentFault 最新的问题
Recent Announcements
Recent Announcements

博客园 - Truly

找不到具有绑定 MetadataExchangeHttpBinding 的终结点的与方案 http 匹配的基址。注册的基址方案是 [https] 生成8位的不重复乱码 省地市级联选择js 继续完善SandCastle 使用SandCastle和ScriptDoc创建JavaScript文档 关于.NET的异常处理的几个误区 JavaScript实现自定义事件 JavaScript面向对象之属性实现 JavaScript随笔一篇 - Truly - 博客园 设计模式在JavaScript中的应用(2) -- Observer 关于JavaScript的“+”运算和“-”运算和三目操作符“?:” - Truly - 博客园 JavaScript面向对象之方法重载 谁动了我的奶酪? 设计模式在JavaScript中的应用(1) 在JavaScript中使用面向对象 对于Asp.Net 2.0中脚本资源的研究(2) 对于Asp.Net 2.0中脚本资源的研究(1) js功能类库放送(二) 调整大小库 js功能类库放送(一) 拖动功能库
微软ASP.NET AJAX中日期类型的JSON处理
Truly · 2007-07-29 · via 博客园 - Truly

作者:Truly
日期:2007.7.29

如我前面文章介绍的那样,JSON在现代JavaScript编程中占据了重要位置,如果你阅读过大型的类库代码,例如AjaxPro,MS ASP.NET AJAX等,你会发现,在组织和交互数据和都普遍采用了JSON方式。我前面那篇文章《

设计模式在JavaScript中的应用(1)》中,使用了较为简单的数据映射,为了避免时区的差别,我将日期用JSON简单表示为如下格式:

"CreateDate":new Date('Wed, 25 Jul 2007 09:59:00 GMT+8')

这样的日期表示在小型应用中具有简单,可读性高的优点,但是对于大型应用程序而言,更好的组织数据,压缩数据,减少通信量则更为重要。今天我们探讨一下微软ASP.NET AJAX中日期类型的JSON处理。

首先看一下ASP.NET AJAX服务器端对日期类型JSON序列化的处理:(详见Ajax扩展源码中的JavaScriptSerializer.cs

internal static readonly long DatetimeMinTimeTicks = (new DateTime(197011000, DateTimeKind.Utc)).Ticks;
private static void SerializeDateTime(DateTime datetime, StringBuilder sb) {
            
        sb.Append(
@"""\/Date(");
        sb.Append((datetime.ToUniversalTime().Ticks 
- DatetimeMinTimeTicks) / 10000);
        sb.Append(
@")\/""");
}

最早期,微软使用下面方法进行序列化:

ASP.NEXT 中的 AJAX JSON 序列化程序将 DateTime 实例编码为 JSON 字符串。在预发布周期中,ASP.NET AJAX 使用格式“@ticks@”,其中 ticks 表示从通用协调时间 (UTC) 1970 年 1 月 1 日起经过的毫秒数。以 UTC 表示的日期和时间(如 1989 年 11 月 29 日 4:55:30 AM)会编码为“@62831853071@”。虽然简单易懂,但此格式无法区分序列化的日期和时间值与看起来像序列化日期但又不需要进行反序列化的值。因此,ASP.NET AJAX 团队对最终版本进行了更改,通过采用“\/Date(ticks)\/”格式解决了这一问题。

新格式借助一个小技巧减少了误解的可能性。在 JSON 中,字符串中的正斜杠 (/) 字符可以用反斜杠 (\) 进行转义(即使没有对此进行严格要求)。ASP.NET AJAX 团队利用这点修改了 JavaScriptSerializer,将 DateTime 实例编写为字符串“\/Date(ticks)\/”。两个正斜杠的转义只是表面的,但对 JavaScriptSerializer 至关重要。按照 JSON 规则,“\/Date(ticks)\/” 在技术上相当于 “/Date(ticks)/”,但 JavaScriptSerializer 会将前者反序列化为 DateTime,将后者反序列化为 String。因此与预发布版本的“@ticks@”格式相比,混淆的可能性会大大减少。

注:此段文字来源于MSDN文章JavaScript 和 .NET 中的 JavaScript Object Notation (JSON) 简介

这里我要补充一个技巧,大家知道,在document中如果出现<script>和</script>那么脚步解释器就会对其中文本进行解析,所以如果你编写下面的代码,则会提示错误:

<script>
document.write(
"<script>alert(1);</script>");
</script>

因为中间出现了“</script>”这样的代码,那么我们可以使用:

<script>
document.write(
"<script>alert(1);</scr"+"ipt>");
</script>

来避免这种错误,这时我们还可以使用“\”来转义:

<script>
document.write(
"<script>alert(1);<\/script>");
</script>

下面我们看ASP.NET AJAX脚本库中对日期的反序列化代码:

Sys.Serialization.JavaScriptSerializer.deserialize = function Sys$Serialization$JavaScriptSerializer$deserialize(data) {
    
/// <param name="data" type="String"></param>
    /// <returns></returns>
    var e = Function._validateParams(arguments, [
        {name: 
"data", type: String}
    ]);
    
if (e) throw e;if (data.length === 0throw Error.argument('data', Sys.Res.cannotDeserializeEmptyString);
                                                            
    
try {    
        
var exp = data.replace(new RegExp('(^|[^\\\\])\\"\\\\/Date\\((-?[0-9]+)\\)\\\\/\\"', 'g'), "$1new Date($2)");
        
return eval('(' + exp + ')');
    }
    
catch (e) {
         
throw Error.argument('data', Sys.Res.cannotDeserializeInvalidJson);
    }
}

我把这个序列化器相关代码整理到Sys.Serialization.js文件中了,有兴趣的可以下载查看。

总结:这样的方式很有参考价值,值得我们在封装数据时借鉴,关于JS对数据的压缩,我前面有一篇简易的作法《压缩JavaScript的宏》,而更加高级的混淆压缩,将留到下一篇文章进行重点研讨。

谢谢阅读。