使用JSON向伺服器發送資料
做了這麼多,你已經能更順手地使用JavaScript了,也許在考慮把更多的模型資訊放在瀏覽器上。不過,看過前面的例子後(使用XML向伺服器發送複雜的資料結構),你可能會改變主意。通過串聯接來建立XML串並不好,這也不是用來產生或修改XML資料結構的健壯技術。JSON概述XML的一個替代方法是JSON,可以在www.json.org找到。JSON是一種文字格式設定,它獨立於具體語言,但是使用了與C系列語言(如C、C#、JavaScript等)類似的約定。JSON建立在以下兩種資料結構基礎上,當前幾乎所有程式設計語言都支援這兩種資料結構:l 名/值對集合。在當前程式設計語言中,這實現為一個對象、記錄或字典。l 值的有序表,這通常實現為一個數組。因為這些結構得到了如此眾多程式設計語言的支援,所以JSON是一個理想的選擇,可以作為異構系統之間的一種資料互換格式。另外,由於JSON是基於標準JavaScript的子集,所以在所有當前Web瀏覽器上都應該是相容的。JSON對象是名/值對的無序集合。對象以 { 開始,以 } 結束,名/值對用冒號分隔。JSON數組是一個有序的值集合,以[ 開始,以 ] 結束,數組中的值用逗號分隔。值可以是串(用雙引號引起)、數值、true或false、對象,或者是數組,因此結構可以嵌套。圖3-6以圖形方式很好地描述了JSON對象的標記。圖3-6
JSON對象結構的圖形化表示(摘自www.json.org)請考慮employee對象的簡單例子。employee對象可能包含名、姓、員工號和職位等資料。使用JSON,可以如下表示employee對象執行個體:var employee = { "firstName" : John , "lastName" : Doe , "employeeNumber" : 123 , "title" : "Accountant"}然後可以使用標準點記法使用對象的屬性,如下所示:var lastName = employee.lastName; //Access the last namevar title = employee.title; //Access the titleemployee.employeeNumber = 456; //Change the employee numberJSON有一點很引以為豪,這就是它是一個輕量級的資料互換格式。如果用XML來描述同樣的employee對象,可能如下所示:<employee> <firstName>John</firstName> <lastName>Doe</lastName> <employeeNumber>123</employeeNumber> <title>Accountant</title></employee>顯然,JSON編碼比XML編碼簡短。JSON編碼比較小,所以如果在網路上發送大量資料,可能會帶來顯著的效能差異。www.json.org網站列出了至少與其他程式設計語言的14種綁定,這說明,不論在伺服器端使用何種技術,都能通過JSON與瀏覽器通訊。使用JSON的樣本(此例子需要json.js,http://www.json.org/js.html 最下面的連結點擊下載,此例子使用的是比較老版本的json.js,如果你下載的是新的,使用的方法就不同了;JSONObject.java,JSONArray.java,http://www.json.org/java/index.html下載,注意不是java JSON-lib雖然裡面也有這兩個類,可能是版本原因不同了如果你要用json-lib,那你就必須下載json-lib-2.0-jdk15.jar,還必需下面5個jar
jakarta commons-lang, jakarta commons-beanutils, jakarta commons-collections
jakarta commons-logging ,ezmorph 缺少任何一個都是不行的,試過了- -!!
前面4個在apache.org下載,最後一個在http://ezmorph.sourceforge.net/下載
下面紅色字型都是分歧部分,就看你是用什麼了,經本人測試沒問題。
)下面是一個簡單的例子,展示了如何使用JSON將JavaScript對象轉換為串格式,並使用Ajax技術將這個串發送到伺服器,然後伺服器根據這個串建立一個對象。這個例子中沒有商務邏輯,也幾乎沒有使用者互動,它強調的是用戶端和伺服器端的JSON技術。圖3-7顯示了一個“字串化的”Car對象。圖3-7
“字串化的”Car對象因為這個例子幾乎與前面的POST例子完全相同,所以我們只關注JSON特定的技術。點擊表單上的按鈕將調用doJSON函數。這個函數首先調用getCarObject函數來返回一個新的Car對象執行個體,然後使用JSON JavaScript庫(可以從www.json.org免費得到)將Car對象轉換為JSON串,再在警告框中顯示這個串。接下來使用XMLHttpRequest對象將JSON編碼的Car對象發送到伺服器。因為有可以免費得到的JSON-Java綁定庫,所以編寫Java servlet來為JSON請求提供服務相當簡單。更妙的是,由於對每種伺服器端技術都有相應的JSON綁定,所以可以使用任何伺服器端技術實現這個例子。圖3-8 讀取JSON串之後的伺服器響應
" hspace="12" src="http://book.csdn.net/bookfiles/11/3/image011.gif" width="268" align="left">JSONExample servlet的doPost方法為JSON請求提供服務。它首先調用readJSONStr- ingFromRequestBody方法從請求體獲得JSON串,然後建立JSONObject的一個執行個體,向JSONObject建構函式提供JSON串。JSONObject在對象建立時自動解析JSON串。一旦建立了JSONObject,就可以使用各個get方法來獲得你感興趣的對象屬性。這裡使用getString和getInt方法來擷取year、make、model和color屬性。這些屬性串連起來構成一個串返回給瀏覽器,並在頁面上顯示。圖3-8顯示了讀取JSON對象之後的伺服器響應。代碼清單3-11顯示了jsonExample.html,代碼清單3-12顯示了JSONExample.java。代碼清單3-11
jsonExample.html<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title>JSON Example</title> <script type="text/javascript" src="json.js"></script><script type="text/javascript"> var xmlHttp; function createXMLHttpRequest() { if (window.ActiveXObject) { xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); } else if (window.XMLHttpRequest) { xmlHttp = new XMLHttpRequest(); }} function doJSON() { var car = getCarObject(); //Use the JSON JavaScript library to stringify the Car object //var carAsJSON = JSON.stringify(car); 老版本的json.js的用法 var carAsJSON = car.toJSONString(); alert("Car object as JSON:/n " + carAsJSON); var url = "JSONExample?timeStamp=" + new Date().getTime(); createXMLHttpRequest(); xmlHttp.open("POST", url, true); xmlHttp.onreadystatechange = handleStateChange; xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;"); xmlHttp.send(carAsJSON);} function handleStateChange() { if(xmlHttp.readyState == 4) { if(xmlHttp.status == 200) { parseResults(); } }} function parseResults() { var responseDiv = document.getElementById("serverResponse"); if(responseDiv.hasChildNodes()) { responseDiv.removeChild(responseDiv.childNodes[0]); } var responseText = document.createTextNode(xmlHttp.responseText); responseDiv.appendChild(responseText);} function getCarObject() { return new Car("Dodge", "Coronet R/T", 1968, "yellow");} function Car(make, model, year, color) { this.make = make; this.model = model; this.year = year; this.color = color;} </script></head> <body> <br/><br/> <form action="#"> <input type="button" value="Click here to send JSON data to the server" onclick="doJSON();"/> </form> <h2>Server Response:</h2> <div id="serverResponse"></div> </body></html>代碼清單3-12
JSONExample.javapackage ajaxbook.chap3; import java.io.*;import java.net.*;import java.text.ParseException;import javax.servlet.*;import javax.servlet.http.*;import org.json.JSONObject;//import net.sf.json.*; public class JSONExample extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String json = readJSONStringFromRequestBody(request); //Use the JSON-Java binding library to create a JSON object in Java JSONObject jsonObject = null; try { //如果是用json-lib的話,前面引進的包改為 //import net.sf.json.*; //這裡改為 //jsonObject = JSONObject.fromObject(json); //fromObject(object)是static的。也可以用fromString(string)的,但官方是不建議用fromString的。 jsonObject = new JSONObject(json); } catch(ParseException pe) { System.out.println("ParseException: " + pe.toString()); } String responseText = "You have a " + jsonObject.getInt("year") + " " + jsonObject.getString("make") + " " + jsonObject.getString("model") + " " + " that is " + jsonObject.getString("color") + " in color."; response.setContentType("text/xml"); response.getWriter().print(responseText); } private String readJSONStringFromRequestBody(HttpServletRequest request){ StringBuffer json = new StringBuffer(); String line = null; try { BufferedReader reader = request.getReader(); while((line = reader.readLine()) != null) { json.append(line); } } catch(Exception e) { System.out.println("Error reading JSON string: " + e.toString()); } return json.toString(); }}