做了这么多,你已经能更顺手地使用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 name
var title = employee.title; //Access the title
employee.employeeNumber = 456; //Change the employee number
JSON有一点很引以为豪,这就是它是一个轻量级的数据互换格式。如果用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绑定,所以可以使用任何服务器端技术实现这个例子。
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"
οnclick="doJSON();"/>
</form>
<h2>Server Response:</h2>
<div id="serverResponse"></div>
</body>
</html>
代码清单3-12
JSONExample.java
package 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();
}
}