本文將解釋如何使用AJAX和JSON分析器在用戶端和伺服器之間建立複雜的JSON資料轉送層。
一、引言
毫無疑問,AJAX已經成為當今Web開發中一種強有力的使用者互動技術,但是它的許多可能性應用仍然鮮為人知。在本文中,我們將來共同探討如何使用JavaScript對象標誌(JSON)和JSON分析器在伺服器和用戶端AJAX引擎之間建立複雜而強有力的JSON資料轉送層。我們將詳細討論如何建立一組對象(在其它語言中經常被當作一個包),如何把這些對象序列化為JSON以發送到伺服器端,以及如何把伺服器端JSON反序列化為用戶端JavaScript對象。
提示:你可以在Douglas Crockford的網站上找到本文中使用的JSON分析器。
在繼續閱讀前,本文假定你已經掌握了JavaScript技術並且瞭解如何建立一個基本的AJAX引擎,並經由AJAX技術向伺服器端發出請求和從伺服器端接收響應。為了更好地理解本文中樣本,你需要下載本文相應的源碼檔案。
二、開始
為了進一步抽象我們的AJAX請求並有助於我們以後在不同的應用程式間共用AJAX引擎代碼,本文使用了一個我自己建立的AJAX引擎。為了使用這個引擎,我們簡單地匯入三個JavaScript檔案並且向一個名為AjaxUpdater的對象發出請求。然後,由該引擎來負責處理其它任務,包括把響應代理到在該請求中指定的回調方法中。下面的樣本展示了我們如何使用這個引擎發出請求以及匯入相關的檔案:
以下是引用片段: <script type="text/javascript"src="javascript/model/Ajax.js"></script> <script type="text/javascript" src="javascript/model/HTTP.js"></script> <script type="text/javascript" src="javascript/model/AjaxUpdater.js"></script> <script type="text/javascript"> document.load = AjaxUpdater.Update(’GET’, URL, callback); </script> |
首先,讓我們來討論JavaScript對象。
三、JavaScript對象
JavaScript以前經常被誤解,似乎它主要用於實現客戶瀏覽器端圖形效果。其實,JavaScript是一種強有力的語言,特別當它與AJAX以及一個應用程式的伺服器端相結合時;但是,即使在用戶端,JavaScript也能夠實現遠比你預料得多的多的功能。物件導向的JavaScript就是一個樣本,它能夠使我們建立對象,擴充內在對象,甚至能夠把我們的對象建立成包以達到更容易的管理之目的。
在本文樣本中,我們將建立三個對象:Auto,Car和Wheel。其中,每一個都是簡單的對象;在此,我們僅使用它們來展示如何建立一個基本包。
首先,Auto對象被聲明為一個新的對象:
以下是引用片段: var Auto = new Object(); |
注意,這個Auto對象將用作Car對象的父類。因此,Car對象將成為Auto對象的一個屬性,只不過它被分離到另一個檔案中以更易於管理(這個概念經常被用於其它物件導向的語言中,但是在JavaScript中卻並不經常提起它)。下面是這個Car對象相應的代碼:
以下是引用片段: Auto.Car = new Object(); Auto.Car.color = "#fff"; Auto.Car.setColor = function(_color) { Auto.Car.color = _color; } Auto.Car.setColor("#333"); |
如你所見,該Car對象是Auto對象的一個子物件—這分明是一種類對象階層。這個對象有一個名為color的屬性和一個用於設定它的方法。在此,我們把color屬性設定為灰色以覆蓋掉預設的白色。當在後面我們序列化該對象時請牢記住這個事實。
下一個對象,Wheel,是Car的一個子物件:
以下是引用片段: Auto.Car.Wheel = new Object(); Auto.Car.Wheel.color = "#000"; |
在此,Wheel是一個基本對象,但是它展示了對象層次中的又一個層。這個對象有一個稱為color的預設值為黑色(“#000”)的屬性。
下面,讓我們來分析一下為什麼這些對象如此重要以及我們是如何使用它們提供的簡單的屬性的。
四、把JavaScript對象序列化為JSON
藉助於JSON分析器,我們可以很容易地把剛才建立的JavaScript對象序列化為JSON。首先,我們需要下載該分析器的一個副本,並且要把它添加到文檔中。下面是我在本文樣本中用於匯入該指令碼的相應的代碼:
以下是引用片段: <script type="text/javascript" src="javascript/utils/jsonparser.js"></script> |
我已經把該分析器添加到我的javascript目錄,即一個稱為utils的子目錄下。
下面是最終的包括到其中用於匯入適當的JavaScript檔案的代碼片斷:
以下是引用片段: <script type="text/javascript" src="javascript/Auto.js"></script> <script type="text/javascript" src="javascript/Car.js"></script> <script type="text/javascript" src="javascript/Wheel.js"></script> <script type="text/javascript" src="javascript/utils/jsonparser.js"></script> <script type="text/javascript" src="javascript/model/Ajax.js"></script> <script type="text/javascript" src="javascript/model/HTTP.js"></script> <script type="text/javascript" src="javascript/model/AjaxUpdater.js"></script> |
在匯入適當的檔案後,我們可以通過把兩個div元素和一個onload事件簡單地添加到HTML文檔中開始序列化。這兩個div元素將分別擁有ID:body和loading。其中,這個loading標籤將由AJAX引擎使用來指示進度情況,而body標籤將用於顯示訊息。
以下是引用片段: <div id="loading"></div> <div id="body"></div> |
onload事件相應於body元素並且設定它的innerHTML 屬性為JavaScript對象(作為一個序列化的JSON字串)。為了實現這一目的,我在Auto對象上使用了jsonparser.js檔案內的toJSONString方法:
以下是引用片段: <body onload="document.getElementById(’body’).innerHTML = ’<b>Local objects serialized as JSON</b> Auto Object: ’+ Auto.toJSONString();"> |
這段代碼使用了Auto對象及其所有的子物件,並且使用JSON分析器的toJSONString方法把它們序列化為一個JSON字串。然後,該資料可以被用作伺服器端的一種資料交換格式。
你可能還記得,在前面我們曾調用了一個稱為setColor的方法來改變Car對象的顏色。當時,我使用它是因為我想向你展示序列化能夠在運行時刻的任何點上實現,而且還為了反映出對象中最新的資料。
如果你仔細分析一下onload事件,你會注意到,Car和Wheel對象都封裝在方括弧內,這些方括弧代表了父物件(即Auto)。這意味著,該序列化的JavaScript對象能夠在運行時刻被發送到伺服器端以儲存最新的資料,並且也可以在應用程式啟動時從伺服器端進行接收以便從資料庫中檢索多數的當前資料。最精彩的部分在於,為了建立一種“無縫”的過程,所有與伺服器之間實現的資料交換都可以使用JSON技術來實現。
下面,讓我們來看一下相同的資料是如何從伺服器端接收的,以及它們是如何被使用最新的資料(典型地,來源於一個資料庫)序列化為用戶端JavaScript對象的。
五、把JSON反序列化為用戶端JavaScript對象
在本文中,我簡單地把一個靜態檔案建立為JSON響應,但是在實際開發中,你可以把這些資料存放區在一個資料庫中並且使用一種伺服器端語言返回它。基於這一能力,我們就可以輕鬆地建立一種強有力的資料交換過程!在前面,我們已經分析了這一序列化過程。憑基本的AJAX體驗,你應該能夠理解資料是如何被寄送到伺服器端的。現在,讓我們著手討論反序列化的問題。首先來看一個針對本文樣本提供的靜態JSON檔案。這個檔案其實是我們在上一節中序列化的資料:
以下是引用片段: {"Car":{"color":"#333","Wheel":{"color":"#000"}}} |
作為一個請求JSON檔案的樣本,當我們點擊下列連結時將請求這個序列化的Auto對象:
以下是引用片段: <a href="javascript:AjaxUpdater.Update(’GET’, ’json/data.js’, displayResponse);">Get remote JSON</a> |
一旦接收到響應訊息,我們的稱為displayResponse回調方法就會被啟用,然後,我們就能夠反序列化並開始使用這些對象:
以下是引用片段: <script type="text/javascript"> function displayResponse() { if(Ajax.checkReadyState(’loading’) == "OK") { var Auto = Ajax.request.responseText.parseJSON(); document.getElementById("body").innerHTML += " <b>Remote JSON unserialized</b>"; document.getElementById("body").innerHTML += " Car color: "+Auto.Car.color; document.getElementById("body").innerHTML += " Wheel color: "+Auto.Car.Wheel.color; } } </script> |
這是相當激動人心的一部分!一旦我們擁有了該responseText,我們就能夠簡單地使用JSON分析器中的parseJSON方法來從序列化的資料中重建我們的Auto對象。藉助於這個新的Auto對象,我們就可以調用相應的子物件。這個特徵允許我們在伺服器和用戶端來回傳送對象—而不必進行大量的分析工作,然而在以前標準的XML響應情況下我們將卻必須這樣做。這樣以來,我們就可以建立出能夠基於AJAX技術來保留自身狀態的用戶端JavaScript對象