DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> JavaScript入門知識 >> JSON基礎 >> XENON基於JSON變種
XENON基於JSON變種
編輯:JSON基礎     
但是在用JSON的過程中,我遇到了一個問題——這個問題想必是大家多少都遇到過,那就是:JSON沒有定義日期和時間的傳遞方式。
盡管在今年3月的一次更新中,json2.js已經增加了對Date函數和ISO-8601式的日期/時間格式,但各種常用的開發工具中對日期的支持還是五花八門、千奇百怪的,完全沒有統一。
而且,除了日期/時間以外,個別時候我們還需要一些類或者函數的支持,而這些都是不被JSON所支持的。

可能有的人看到這裡要問了:既然JSON不支持,那為什麼不去用別的數據描述/傳輸方式呢?
原因是JSON本身就是JavaScript(其參考標准為ECMAScript)的功能子集,任何稍懂JavaScript的人都可以輕松地利用JSON。

解析JSON最簡單的辦法是直接使用eval函數將其作為JavaScript代碼來執行,而JSON常常被用在互聯網上的不同應用之間傳遞,所以直接將收到的JSON內容傳入eval函數是具有很大的風險的,因此在RFC文檔中嚴格規定了JSON的格式,並且給出了檢驗其安全性的辦法。
而這個檢驗辦法就禁止了函數的運行。

總而言之,因為JSON在使用上“偶爾”會有些不方便,所以我就開始動腦筋擴展JSON了。


在參考了RFC-4627、json2.js以及一些常見的JavaScript語法著色器以後,我發現:雖然json2.js已經有了對日期/時間的支持,但它所采用的語法分析的模式,這就意味著如果不是對語法分析有一定的了解,是很難對它進行擴展的;即使我稍微研習過一些語法分析的知識,想要擴展它也並非很容易的事情,更別談日後的維護了。
所以我決定用RFC-4627中建議的較為簡單的正則表達式過濾法。

這個擴展的基本實現是這樣的:
復制代碼 代碼如下:
function Xenon(){}
var protoXenon = Xenon.prototype;
protoXenon.xeval = function(s){
var al = [], vl = [], ol = {};
function $(i, v){
// i = parseInt(i);
// return ol[i] || (ol[i] = v);
return ol.propertyIsEnumerable(i) ? ol[i] : (ol[i] = v);
}
for(var n in this)
if(this.propertyIsEnumerable(n) && typeof this[n] == 'function')
al.push(n), vl.push(this[n]);
return eval('0,function(' + al + '){return ' + s + ';}').apply(this, vl);
};
protoXenon.safeXeval = function(s){
var T = this;
return (!/[^\),:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(
s.replace(/"(\\.|[^"\\])*"/g, '')
.replace(/([^\s:\[,\(]+?)\(/g,function($0, $1){
// return T.propertyIsEnumerable($1) ? '' : $1 + '(';
return T.propertyIsEnumerable($1) ? '' : '@';
})) || null) &&
this.xeval(s);
};

基本用法就是創建一個xenon對象,為其設置新的成員以啟用擴展函數。
可以把擴展函數直接添加到xenon對象上,也可以在全局作用域中聲明函數再在xenon對象上設置非函數類型的成員值。
例子:
復制代碼 代碼如下:
var xenon = new Xenon();
xenon.Array = 0;
xenon.$ = 0;
xenon.date = function(s){return new Date(s);};
var o = xenon.safeXeval('{"list":Array(3,6,9),"created":$(1,date("Tue Jul 27 02:48:03 UTC+0800 2010")),"modified":$(1)}');
print(o.list);
print(o.created);
print(o.modified == o.created);

注:這個例子並不能直接作為JScript.NET代碼執行,若要在JScript.NET中使用則必須將字符串"unsafe"作為第二個參數傳遞給eval函數。
注2:function關鍵字前增加“0,”是為了兼容於IE所使用的JScript引擎——當前的非CLI版本JScript引擎在其eval的實現中並不能正確地理解包圍著函數定義的圓括號的意義,會因此引發語法錯誤。
在這個例子中使用了三個函數擴展:Array為全局作用域中的JavaScript內置函數;$是我在XENON中實現的內置功能,可以在多處引用同一個對象;而date則是對Date構造器的包裝。
在XENON的實現中我沒有讓它支持new操作符創建新對象,我沒發現有要用new而不能直接用擴展函數的理由。

關於名字:起初打算叫做xJson,但是後來想想覺得有點遜,改作XEON(eXtensible ECMAScript Object Notation)之後又發現好像是Intel的注冊商標,所以在中間多加了個N變成了XENON(eXtensible Native ECMAScript Object Notation)。查了下字典,是個化學元素的名字……就這麼湊合用吧。
關於安全性:在設計檢驗方法的過程中我盡可能測試了我所想得到的字符組合,力求避免注入問題。但是由於缺乏實踐檢驗,我也不擅長語法分析之類的事情,所以可能並不是絕對安全。如果誰發現了其中的安全漏洞,可以通知我來改進它。
以後有時間我會做一個簡單的從ECMAScript對象向XENON轉換的函數;如果真的有很充裕的時間,也許我還會實現包含類名和構造器的轉換過程。
XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved