精通JSON (JavaScript Object Notation)

JSON被公认为浏览器中XML的后继者,它的目标仅仅是成为一种简单、优雅的数据格式,以方便浏览器和服务器之间的数据交换。在完成这一简单任务的过程中,它将引领下一代万维网。
对象简介

看,这就是一个对象:

var myFirstObject ={};

尽管看起来挺简单,然而那些花括号却能够记录人类所搜集的信息的每个比特,或者是表示出计算机科学家们能构思到的最复杂的程序.事实上,Javascript本身就是存储在那样一个花括号集合中的,包括它所有的基本类型 -- 字符串,数字,数组,日期,正则表达式,它们都是对象,都是像上面myFirstObject那样开始的.
创建一个新对象


旧的方式是使用"new"关键字创建新对象.

var myJSON =newObject();



这种方式已经过时,现在流行的方式是通过一对大括号定义一个空对象...

var myJSON ={};


对象即数据


在Javascript对象的最底层是一种很灵活且健壮的数据格式,表示为“名/值对”。也就是说,一个对象的属性名--可以看作是依附在对象名上的一个普通变量.并且这个对象保存着上述名字的值.看下面的例子...

var myFirstJSON ={"firstName":"John",
"lastName" :"Doe",
"age" :23};

document.writeln(myFirstJSON.firstName); // 输出John
document.writeln(myFirstJSON.lastName); // 输出Doe
document.writeln(myFirstJSON.age); // 输出23

这个对象有3个属性或者说名/值对.在这个例子中,firstName,lastName,还有age这些名字是字符串类型.而值可以是任何的 javascript对象(请记住javascript中一切介对象,所以这个值可以是字符串,数字,数组,函数,还有其它对象类型) -- 在这个例子中,我们的值是John,Doe,还有23.John与Doe是字符串但age是数字,如你所见,这都不是问题.
这种数据格式称为JSON,JSON是JavaScript Object Notation的缩写.它能如此强大的原因是它的值可以是任何数据类型,你可以保存不同的数组与对象,按你的需要去尽情嵌套.下面是一个稍等复杂点的JSON结构...

var employees ={"accounting":[ // accounting is an array in employees.
{"firstName":"John", // First element
"lastName" :"Doe",
"age" :23},

{"firstName":"Mary", // Second Element
"lastName" :"Smith",
"age" :32}
],// End "accounting" array.
"sales" :[// Sales is another array in employees.
{"firstName":"Sally",// First Element
"lastName" :"Green",
"age" :27},

{"firstName":"Jim", // Second Element
"lastName" :"Galley",
"age" :41}
]// End "sales" Array.
}// End Employees

这里的employees是一个对象.它有两个属性或者说名值对.Accounting是一个拥有两个JSON对象的数组,分别表示了两个雇员的名字与年龄信息.同样地,sales也是一个拥有两个JSON对象的数组,分别表示了两名工作在销售部门员工的名字与年龄.所有这些数都保存在employees对象中.访问这些数据有几种不同的方式.
访问JSON中的数据

最常见的访问JSON数据的方式就是通过点标记.这仅仅在对象名字后面跟一个句点与要访问的属性名.如果你的对象中包含另一个对象,那只要再添加上点与对象名就可以了...

var myObject ={'color':'blue',
'animal':{'dog':'friendly'}
};

document.writeln(myObject.animal.dog);// 输出friendly


以上面的"employee"为例,如果我们想访问在"sales"工作的第一个员工信息...

document.writeln(employees.sales[0].firstName +' '+ employees.sales[0].lastName);


我们也可以访问“accounting”中的第二个员工信息.

document.writeln(employees.accounting[1].firstName +' '+ employees.accounting[1].lastName);


总的来说,这个的例子的"employee"就是一个拥有两个数组的对象,每个数组中分别拥有两个附加对象.这种结构的唯一限制就是存储的大小和可用内存. 因为JSON可以保存一切对象,包括深层嵌套的对象,所以它的保存内容无任何限制.如果有足够的内存及储存条件,一个简单的JSON数据结构可以存储并正确地索引迄今人类产生的所有信息.
像关联数组一样访问对象



你也可以把JSON当作一个关联数组一样访问数据.

var myFirstJSON ={"firstName":"John",
"lastName" :"Doe",
"age" :23};

document.writeln(myFirstJSON["firstName"]); // 输出John
document.writeln(myFirstJSON["lastName"]); // 输出Doe
document.writeln(myFirstJSON["age"]); // 输出23

要注意的是,上面的例子虽然看起来像关联数组,实质上并不是.当你遍历整myFirstObject对象的时候,除了上面三个属性之外,你还会得到分配到这个对象的其它方法与属性,所以,当你使用上面例子的方式定位JSON数据时,要把它当作是一个对象来看,而不是关联数组.
通过AJAX接收JSON数据


通过AJAX接收JSON数据有三个不同方式.委派,回调与解释.
通过委派得到JSON



这个方法没有标准命名约定,不过"委派法"倒是一个挺好的描述名字,因为服务器创建的javascript表达式文件会把JSON分派到一个变量 中.当把服务器的返回文本作为参数传给eval函数时,someVar变量就会装载JSON对象,然后你就可以通过这个变量访问.

varJSONFile="someVar = { 'color' : 'blue' }"; // example of what is received from the server.服务器返回数据示例
eval(JSONFile);// Execute the javascript code contained in JSONFile.执行JSONFile中的javascript代码.

document.writeln(someVar.color);// 输出'blue'


通过回调得到JSON



第二个方法预先定义一个以JSON数据作为参数的函数,然后服务器返回的javascript表达式中调用这个函数.这个方法叫"回调法".这个方式被广泛地应用在处理第三方JSON数据中(例如,从其它域名获取的JSON数据)

function processData(incommingJSON){
document.writeln(incommingJSON.color);// 输出'blue'
}

// example of what is received from the server...
varJSONFile="processData( { 'color' : 'blue' } )";

eval(JSONFile);


通过解析获取JSON



最后这个方法通过一个解析函数解析原始对象文本取得JSON.这可称为"解析法".这是迄今为止最安全的传输JSON数据的方式,并且这个方式将成为下一版javascript(预计在2008年发布)的一部分.目前,非常不幸地,你在你能控制的范围内使用.

// The following block implements the string.parseJSON method 下面代码块实现了string.parseJSON方法
(function(s){
// This prototype has been released into the Public Domain, 2007-03-20
// Original Authorship: Douglas Crockford
// Originating Website: http://www.JSON.org
// Originating URL : http://www.JSON.org/JSON.js

// 增强String原型.我们利用这个即时执行的匿名函数避免使用全局变量.
// m是转义字符表

var m ={
'\b':'\\b',
'\t':'\\t',
'\n':'\\n',
'\f':'\\f',
'\r':'\\r',
'"':'\\"',
'\\':'\\\\'
};

s.parseJSON =function(filter){

// 解析分三步进行,第一步,我们先用正则表达式过滤非JSON字符.我们会特别关注"()"与"new",因为它们
// 会触发调用,还有"=",它会导致赋值从而发生变化.为了安全,我们会丢弃所有不期待的字符.

try{
if(/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/.
test(this)) {

// 在第二步,我们使用eval函数把文本编译到一个JavaScript结构中去.在javascript中"{"操作符容易导致语法混淆:它可以是一个代码块的开始或者一个对象直接量.我们在外层包装上括号避免混淆.

var j = eval('(' + this + ')');

// 第三步是可选的,我们递归遍历这个新结构,把每个名/值对传递到一个过滤函数,以便做一些转换.

if (typeof filter === 'function') {

function walk(k, v) {
if (v && typeof v === 'object') {
for (var i in v) {
if (v.hasOwnProperty(i)) {
v[i] = walk(i, v[i]);
}
}
}
return filter(k, v);
}

j = walk('', j);
}
return j;
}
} catch (e) {

// Fall through if the regexp test fails.

}
throw new SyntaxError("parseJSON");
};
}
) (String.prototype);
// End public domain parseJSON block

// begin sample code (still public domain tho)
JSONData = '{"color" : "green"}'; // Example of what is received from the server.
testObject=JSONData.parseJSON();
document.writeln(testObject.color); // Outputs: Green.

正如你看到的,你需要在解析JSON数据的地方引入上面的原型方法,一旦你引入了,处理JSON数据就变得非常简单,就像上面例子最后所示,只需三行代码. 在上述三个方法中,"解析法"是最安全并且使你的代码暴露最少.你应该在用到JSON的AJAX应用中尽可能使用此方法.
通过AJAX检索JSON数据

下面的例子会使用这篇文章 介绍的AJAX框架,参考: The Ultimate Ajax Object.

当你需要与服务器交互时,从服务器到浏览器,AJAX是个较好的数据传输方式.假若服务器是在你控制范围内,使用这个方法传输是绝对安全的.下面的例子演示了通过一个简单的AJAX请求与服务通讯,获取一些数据,并传递给一个处理函数.在这里我们将使用回调法,当JSON数据加载完后,它会被一个预定义的函数processData(JSONData)执行处理.

function processData(JSONData){
alert(JSONData.color);
}

var ajaxRequest =new ajaxObject('http://www.somedomain.com/getdata.php');
ajaxRequest.callback =function(responseText){
eval(responseText);
}
ajaxRequest.update();

// In this example we assume the server sends back the following data file
// (which the ajax routine places in responseText)
//
// processData( { "color" : "green" } )



我们这个例子中的数据文件,实际上是一些javascript代码,当它被传递到eval语句中时会执行processData函数,把实际的JSON数据作为参数传递给这个函数.下一个例子中,我们会使用解析法,请确保你代码的其它地方有parseJSON的原型定义.

function processData(JSONData){
alert(JSONData.color);
}

var ajaxRequest =new ajaxObject('http://www.somedomain.com/getdata.php');
ajaxRequest.callback =function(responseText){
JSONData= responseText.parseJSON();
processData(JSONData);
}
ajaxRequest.update();

// In this example we assume the server sends back the following data file
// (which the ajax routine places in responseText)
//
// { "color" : "green" }

现在,当服务返回JSON文件时,它会被“JSONData = responseText.parseJSON();”这段代码解析并且把结果JSONData传递给处理函数processData.得到的结果与第一个例子一样,不过,由于某些原因,当JSON数据中含有恶意代码或非法数据时,使用第二个方法会更安全,而且便于处理各种问题.
如何发送JSON数据到服务器

由于AJAX把数据当作编码好的字符串发送,这样在发送到服务器前就需要对JSON数据做一些准备工作.非常幸运,Douglas Crockford已经在JSON.org发布了一些非常有用的通用代码,可以把javascript数据类型转换成便于发送到服务器的JSON字符串.

这个库的源代码可能可以通过http://www.JSON.org/JSON.js获取.这些代码的使用是没有任何约束的,你可以复制粘贴到你的工具箱中.

下面这个例子定义了一个JSON对象,然后使用toJSONString()方法把这个对象转换成准备发送到服务器的字符串.

var employees ={"accounting":[ // accounting is an array in employees.
{"firstName":"John", // First element
"lastName" :"Doe",
"age" :23},

{"firstName":"Mary", // Second Element
"lastName" :"Smith",
"age" :32}
],// End "accounting" array.
"sales" :[// Sales is another array in employees.
{"firstName":"Sally",// First Element
"lastName" :"Green",
"age" :27},

{"firstName":"Jim",// Second Element
"lastName" :"Galley",
"age" :41}
]// End "sales" Array.
}// End Employees

var toServer = employees.toJSONString();

document.writeln(toServer);

输出:

//{"accounting":[{"firstName":"John","lastName":"Doe","age":23},{"firstName":"Mary","lastName":"Smith","age":32}],"sales":[{"firstName":"Sally","lastName":"Green","age":27},{"firstName":"Jim","lastName":"Galley","age":41}]}


从第三方服务获取JSON

本节将看到啰嗦的忠告.到目前为止,JSON与AJAX相对来说还是安全的,因为交互的服务与获取的数据都在你的控制范围内.但对于第三方服务来说,这一切都改变了.
在IE7与Firefox2中,使用第三方的JSON数据将会使你的网页面临恶意攻击及重大的安全风险.当你请求第三方的数据时,你就相当于失去了页面的控制权,而第三方可以为所欲为地从页面搜刮数据并把敏感信息回发,然后再安装个监听器等待敏感数据.
可以确定的是,请求外部的JSON你唯一得到的就是一堆有用的数据.然而,如果页面上包含表单元素,请求安全/加密链接,或者包含其它任何个人隐私数据的,绝不能在此页面上使用第三方的JSON调用.
当你尝试使用第三方的JSON数据去美化,充实你创建的页面时,你想象一下现在世界上最坏的人正在和你一起看着这个页面.如果其他人可以使相关信息显示在这个页面上让你觉得不舒服,那就不要使用第三方JSON调用.
除了RSS/XML之外,不少服务开始提供JSON这种数据格式.特别是Yahoo,是实施JSON的先驱.JSON最酷的地方就是页面可以直接请求并处理它的数据,不同于XML,得先向服务器请求再传递给浏览器.但非常不幸,现在还没有JSON的RSS/FEED标准,虽然很多服务都模拟了JSON结构的RSS XML.

下面的例子中,我们会使用本站的JSON feed,非常简单的XML到JSON一对一转换.这个FEED甚至与生成XML版本的是同一个程序,只是url传递的参与去决定选择哪种格式.下面是本站FEED的链接:

http://www.hunlock.com/feed.php?format=JSON&callback=JSONFeed



所有第三方JSON要求使用回调方法的地方,当JSON数据文件被加载完成后都会调用一个特别函数,并把JSON数据作为这个函数的第一个参数.很多服务都有一个默认的调用函数,而一些服务能让你自己指定这个调用函数的名字.我的JSON feed默认会调用 JSONFeed(),但你可以通过URL去改变这个函数名. 假如你改变读取的URL如下:

http://www.hunlock.com/feed.php?format=JSON&callback=processJSON

现在,当Feed被加载完成后,它会调用"processJSON"函数,并把JSON数据作为首个参数传递进去.这个对你需要处理多个JSON请求的时候尤为重要.

所有第三方JSON请求都通过

你可能感兴趣的:(Javascript,json,JavaScript,Ajax,应用服务器,数据结构,ViewUI)