`
luozhonghua2014
  • 浏览: 62415 次
文章分类
社区版块
存档分类
最新评论

js与json交互理论和示例

 
阅读更多

详细说明了理论和技巧,现实开发工作意义大


JSON 的语法可以表示以下三种类型的值。
 简单值:使用与 JavaScript 相同的语法,可以在 JSON 中表示字符串、数值、布尔值和 null 。
但 JSON 不支持 JavaScript 中的特殊值 undefined 。
 对象:对象作为一种复杂数据类型,表示的是一组无序的键值对儿。而每个键值对儿中的值可
以是简单值,也可以是复杂数据类型的值。
 数组:数组也是一种复杂数据类型,表示一组有序的值的列表,可以通过数值索引来访问其中
的值。数组的值也可以是任意类型——简单值、对象或数组。
JSON 不支持变量、函数或对象实例,它就是一种表示结构化数据的格式,虽然与 JavaScript 中表示
数据的某些语法相同,但它并不局限于 JavaScript 的范畴。
20.1.1 简单值

最简单的 JSON 数据形式就是简单值。例如,下面这个值是有效的 JSON 数据:

5
这是 JSON 表示数值 5 的方式。类似地,下面是 JSON 表示字符串的方式:
"Hello world!"
JavaScript 字符串与 JSON 字符串的最大区别在于,JSON 字符串必须使用双引号(单引号会导致语
法错误) 。

布尔值和 null 也是有效的 JSON 形式。但是,在实际应用中,JSON 更多地用来表示更复杂的数据
结构,而简单值只是整个数据结构中的一部分。
20.1.2 对象
JSON 中的对象与 JavaScript 字面量稍微有一些不同。下面是一个 JavaScript 中的对象字面量:
var person = {
name: "Nicholas",
age: 29
};
这虽然是开发人员在 JavaScript 中创建对象字面量的标准方式,但 JSON 中的对象要求给属性加引
号。实际上,在 JavaScript 中,前面的对象字面量完全可以写成下面这样:
var object = {
"name": "Nicholas",
"age": 29
};
JSON 表示上述对象的方式如下:
{
"name": "Nicholas",
"age": 29
}
与 JavaScript 的对象字面量相比,JSON 对象有两个地方不一样。

首先,没有声明变量(JSON 中没有变量的概念) 。

其次,没有末尾的分号(因为这不是 JavaScript 语句,所以不需要分号) 。

再说一遍,
对象的属性必须加双引号,这在 JSON 中是必需的。属性的值可以是简单值,也可以是复杂类型值,因
此可以像下面这样在对象中嵌入对象:
{
"name": "Nicholas",
"age": 29,
"school": {
"name": "Merrimack College",
"location": "North Andover, MA"
}
}
这个例子在顶级对象中嵌入了学校( "school" )信息。虽然有两个 "name" 属性,但由于它们分别
属于不同的对象,因此这样完全没有问题。不过,同一个对象中绝对不应该出现两个同名属性。
与 JavaScript 不同,JSON 中对象的属性名任何时候都必须加双引号。手工编写 JSON 时,忘了给对
象属性名加双引号或者把双引号写成单引号都是常见的错误。

20.1.3 数组
JSON 中的第二种复杂数据类型是数组。JSON 数组采用的就是 JavaScript 中的数组字面量形式。例
如,下面是 JavaScript 中的数组字面量:
var values = [25, "hi", true];
在 JSON 中,可以采用同样的语法表示同一个数组:
[25, "hi", true]
同样要注意,JSON 数组也没有变量和分号。把数组和对象结合起来,可以构成更复杂的数据集合,
例如:
[
{
"title": "Professional JavaScript",
"authors": [
"Nicholas C. Zakas"
],
edition: 3,
year: 2011
},
{
"title": "Professional JavaScript",
"authors": [
"Nicholas C. Zakas"
],
edition: 2,
year: 2009
},
{
"title": "Professional Ajax",
"authors": [
"Nicholas C. Zakas",
"Jeremy McPeak",
"Joe Fawcett"
],
edition: 2,
year: 2008
},
{
"title": "Professional Ajax",
"authors": [
"Nicholas C. Zakas",
"Jeremy McPeak",
"Joe Fawcett"
],
edition: 1,
year: 2007
},
{
"title": "Professional JavaScript",
"authors": [
"Nicholas C. Zakas"
],
edition: 1,

year: 2006
}
]
这个数组中包含一些表示图书的对象。每个对象都有几个属性,其中一个属性是 "authors" ,这个
属性的值又是一个数组。对象和数组通常是 JSON 数据结构的最外层形式(当然,这不是强制规定的) ,
利用它们能够创造出各种各样的数据结构。
20.2 解析与序列化
JSON 之所以流行,拥有与 JavaScript 类似的语法并不是全部原因。更重要的一个原因是,可以把
JSON 数据结构解析为有用的 JavaScript 对象。与 XML 数据结构要解析成 DOM 文档而且从中提取数据
极为麻烦相比,JSON 可以解析为 JavaScript 对象的优势极其明显。就以上一节中包含一组图书的 JSON
数据结构为例,在解析为 JavaScript 对象后,只需要下面一行简单的代码就可以取得第三本书的书名:
books[2].title
当然, 这里是假设把解析 JSON 数据结构后得到的对象保存到了变量 books 中。 再看看下面在 DOM
结构中查找数据的代码:
doc.getElementsByTagName("book")[2].getAttribute("title")
看看这些多余的方法调用,就不难理解为什么 JSON 能得到 JavaScript 开发人员的热烈欢迎了。从
此以后,JSON 就成了 Web 服务开发中交换数据的事实标准。
20.2.1 JSON对象
早期的 JSON 解析器基本上就是使用 JavaScript 的 eval() 函数。由于 JSON 是 JavaScript 语法的子
集,因此 eval() 函数可以解析、解释并返回 JavaScript 对象和数组。ECMAScript 5 对解析 JSON 的行
为进行规范,定义了全局对象 JSON 。支持这个对象的浏览器有 IE 8+、Firefox 3.5+、Safari 4+、Chrome
和 Opera 10.5+。 对于较早版本的浏览器, 可以使用一个 shim: https://github.com/douglascrockford/JSON-js。
在旧版本的浏览器中,使用 eval() 对 JSON 数据结构求值存在风险,因为可能会执行一些恶意代码。
对于不能原生支持 JSON 解析的浏览器,使用这个 shim 是最佳选择。
JSON 对象有两个方法: stringify() 和 parse() 。在最简单的情况下,这两个方法分别用于把
JavaScript 对象序列化为 JSON 字符串和把 JSON 字符串解析为原生 JavaScript 值。例如:
var book = {
title: "Professional JavaScript",
authors: [
"Nicholas C. Zakas"
],
edition: 3,
year: 2011
};
var jsonText = JSON.stringify(book);

这个例子使用 JSON.stringify() 把一个 JavaScript 对象序列化为一个 JSON 字符串,然后将它保
存在变量 jsonText 中。默认情况下, JSON.stringify() 输出的 JSON 字符串不包含任何空格字符或
缩进,因此保存在 jsonText 中的字符串如下所示:
{"title":"Professional JavaScript","authors":["Nicholas C. Zakas"],"edition":3,"year":2011}
在序列化 JavaScript 对象时,所有函数及原型成员都会被有意忽略,不体现在结果中。此外,值为
undefined 的任何属性也都会被跳过。结果中最终都是值为有效 JSON 数据类型的实例属性。
将 JSON 字符串直接传递给 JSON.parse() 就可以得到相应的 JavaScript 值。例如,使用下列代码
就可以创建与 book 类似的对象:
var bookCopy = JSON.parse(jsonText);
注意,虽然 book 与 bookCopy 具有相同的属性,但它们是两个独立的、没有任何关系的对象。
如果传给 JSON.parse() 的字符串不是有效的 JSON,该方法会抛出错误。
20.2.2 序列化选项
实际上, JSON.stringify() 除了要序列化的 JavaScript 对象外,还可以接收另外两个参数,这两
个参数用于指定以不同的方式序列化 JavaScript 对象。第一个参数是个过滤器,可以是一个数组,也可
以是一个函数;第二个参数是一个选项,表示是否在 JSON 字符串中保留缩进。单独或组合使用这两个
参数,可以更全面深入地控制 JSON 的序列化。
1. 过滤结果
如果过滤器参数是数组,那么 JSON.stringify() 的结果中将只包含数组中列出的属性。来看下
面的例子。
var book = {
"title": "Professional JavaScript",
"authors": [
"Nicholas C. Zakas"
],
edition: 3,
year: 2011
};
var jsonText = JSON.stringify(book, ["title", "edition"]);
JSONStringifyExample01.htm
JSON.stringify() 的第二个参数是一个数组,其中包含两个字符串: "title" 和 "edition" 。
两个属性与将要序列化的对象中的属性是对应的, 因此在返回的结果字符串中, 就只会包含这两个属性:
{"title":"Professional JavaScript","edition":3}

如果第二个参数是函数,行为会稍有不同。传入的函数接收两个参数,属性(键)名和属性值。根
据属性(键)名可以知道应该如何处理要序列化的对象中的属性。属性名只能是字符串,而在值并非键值对儿结构的值时,键名可以是空字符串。
为了改变序列化对象的结果,函数返回的值就是相应键的值。不过要注意,如果函数返回了

undefined ,那么相应的属性会被忽略。还是看一个例子吧。

var book = {
"title": "Professional JavaScript",
"authors": ["Nicholas C. Zakas","xxxx.xxx"],
edition: 3,
year: 2011
};
var jsonText = JSON.stringify(book,
function(key, value) {
switch (key) {
case "authors":
return value.join(",")
case "year":
return 5000;
case "edition":
return undefined;
default:
return value;
}
});

console.log(jsonText);//{"title":"Professional JavaScript","authors":"Nicholas C. Zakas,xxxx.xxx","year":5000}


这里,函数过滤器根据传入的键来决定结果。如果键为 "authors" ,就将数组连接为一个字符串;
如果键为 "year" ,则将其值设置为 5000 ;如果键为 "edition" ,通过返回 undefined 删除该属性。
最后,一定要提供 default 项,此时返回传入的值,以便其他值都能正常出现在结果中。实际上,第
一次调用这个函数过滤器,传入的键是一个空字符串,而值就是 book 对象。序列化后的 JSON 字符串
如下所示:
{"title":"Professional JavaScript","authors":"Nicholas C. Zakas","year":5000}
要序列化的对象中的每一个对象都要经过过滤器, 因此数组中的每个带有这些属性的对象经过过滤
之后,每个对象都只会包含 "title" 、 "authors" 和 "year" 属性。
Firefox 3.5 和 3.6 对 JSON.stringify() 的实现有一个 bug,在将函数作为该方法的第二个参数时
这个 bug 就会出现,即这个函数只能作为过滤器:返回 undefined 意味着要跳过某个属性,而返回其
他任何值都会在结果中包含相应的属性。Firefox 4 修复了这个 bug。
2. 字符串缩进
JSON.stringify() 方法的第三个参数用于控制结果中的缩进和空白符。
如果这个参数是一个数
值,那它表示的是每个级别缩进的空格数。例如,要在每个级别缩进 4 个空格,可以这样写代码:
var book = {
"title": "Professional JavaScript",
"authors": [
"Nicholas C. Zakas"
],
edition: 3,
year: 2011

};
var jsonText = JSON.stringify(book, null, 4);
JSONStringifyExample03.htm
保存在 jsonText 中的字符串如下所示:
{
"title": "Professional JavaScript",
"authors": [
"Nicholas C. Zakas"
],
"edition": 3,
"year": 2011
}
不知道读者注意到没有, JSON.stringify() 也在结果字符串中插入了换行符以提高可读性。只要
传入有效的控制缩进的参数值,结果字符串就会包含换行符。 (只缩进而不换行意义不大。 )最大缩进空
格数为 10,所有大于 10 的值都会自动转换为 10。
如果缩进参数是一个字符串而非数值,则这个字符串将在 JSON 字符串中被用作缩进字符(不再使
用空格) 。在使用字符串的情况下,可以将缩进字符设置为制表符,或者两个短划线之类的任意字符。
var jsonText = JSON.stringify(book, null, " - -");
这样, jsonText 中的字符串将变成如下所示:
{
--"title": "Professional JavaScript",
--"authors": [
----"Nicholas C. Zakas"
--],
--"edition": 3,
--"year": 2011
}
缩进字符串最长不能超过 10 个字符长。如果字符串长度超过了 10 个,结果中将只出现前 10 个字
符。
3. toJSON() 方法
有时候, JSON.stringify() 还是不能满足对某些对象进行自定义序列化的需求。在这些情况下,
可以给对象定义 toJSON() 方法, 返回其自身的 JSON 数据格式。 原生 Date 对象有一个 toJSON() 方法,
能够将JavaScript的 Date 对象自动转换成ISO 8601日期字符串 (与在 Date 对象上调用 toISOString()
的结果完全一样) 。可以为任何对象添加 toJSON() 方法,比如:

var book = {
"title": "Professional JavaScript",
"authors": ["Nicholas C. Zakas"],
edition: 3,
year: 2011,
toJSON: function() {
return this.title;
}
};
var jsonText = JSON.stringify(book);
console.log(jsonText);// "Professional JavaScript"


以上代码在 book 对象上定义了一个 toJSON() 方法,该方法返回图书的书名。与 Date 对象类似,
这个对象也将被序列化为一个简单的字符串而非对象。可以让 toJSON() 方法返回任何值,它都能正常
工作。比如,可以让这个方法返回 undefined ,此时如果包含它的对象嵌入在另一个对象中,会导致
它的值变成 null ,而如果它是顶级对象,结果就是 undefined 。
toJSON() 可以作为函数过滤器的补充,因此理解序列化的内部顺序十分重要。假设把一个对象传
入 JSON.stringify() ,序列化该对象的顺序如下。
(1) 如果存在 toJSON() 方法而且能通过它取得有效的值,则调用该方法。否则,返回对象本身。
(2) 如果提供了第二个参数,应用这个函数过滤器。传入函数过滤器的值是第(1)步返回的值。
(3) 对第(2)步返回的每个值进行相应的序列化。
(4) 如果提供了第三个参数,执行相应的格式化。
无论是考虑定义 toJSON() 方法,还是考虑使用函数过滤器,亦或需要同时使用两者,理解这个顺
序都是至关重要的。

20.2.3 解析选项
JSON.parse() 方法也可以接收另一个参数,该参数是一个函数,将在每个键值对儿上调用。为了
区别 JSON.stringify() 接收的替换(过滤)函数(replacer) ,这个函数被称为还原函数(reviver) ,
但实际上这两个函数的签名是相同的——它们都接收两个参数,一个键和一个值,而且都需要返回一
个值。
如果还原函数返回 undefined ,则表示要从结果中删除相应的键;如果返回其他值,则将该值插
入到结果中。在将日期字符串转换为 Date 对象时,经常要用到还原函数。例如:

var book = {
"title": "Professional JavaScript",
"authors": ["Nicholas C. Zakas"],
edition: 3,
year: 2011,
releaseDate: new Date(2011, 11, 1) //新增
};
var jsonText = JSON.stringify(book);
var bookCopy = JSON.parse(jsonText,
function(key, value) {
if (key == "releaseDate") {
return new Date(value);
} else {
return value;
}
});
console.log(bookCopy.releaseDate.getFullYear()); //2011

以上代码先是为 book 对象新增了一个 releaseDate 属性,该属性保存着一个 Date 对象。这个
对象在经过序列化之后变成了有效的 JSON 字符串,然后经过解析又在 bookCopy 中还原为一个 Date
对象。还原函数在遇到 "releaseDate" 键时,会基于相应的值创建一个新的 Date 对象。结果就是
bookCopy.releaseDate 属性中会保存一个 Date 对象。正因为如此,才能基于这个对象调用
getFullYear() 方法。


分享到:
评论

相关推荐

    json和jquery交互

    在提供的压缩包"Test"中,可能包含了相关的示例代码或测试用例,可以帮助你理解和实践JSON与jQuery的交互。记得解压并查看文件内容以获取更多细节。通过深入学习和实践这些知识点,你将能够更好地掌握JSON和jQuery在...

    一个使用JSON-lib和json2.js的示例

    在上述的“一个使用JSON-lib和json2.js的示例”中,我们可以假设这是一个关于如何在Java后端与JavaScript前端之间通过JSON进行数据交互的教学示例。首先,开发者可能会在Java端使用JSON-lib来将处理后的业务数据转换...

    Android客户端与服务端的JSON交互数据的实现

    总结,Android客户端与服务端的JSON交互数据涉及JSON的解析和生成、网络通信、错误处理等多个方面。理解并熟练运用这些知识点,对于开发功能丰富的Android应用至关重要。通过不断实践和优化,可以提升应用程序的用户...

    Android高级应用源码-客户端与服务端的json交互的小例子.rar

    本资源"Android高级应用源码-客户端与服务端的json交互的小例子"提供了一个具体的示例,帮助开发者理解和实践Android应用如何通过JSON进行数据通信。 1. JSON基础知识: JSON(JavaScript Object Notation)是一种...

    javascript处理json字符串和json对象的类(含示例)

    `JSON.parse()`和`JSON.stringify()`是JavaScript处理JSON的核心工具,而实际项目中的HTML和JS文件则负责提供交互式用户体验。通过结合使用这些工具和技术,开发者能够轻松地在前端和后端之间传递和操作数据。

    客户端与服务端的json交互的小例子

    JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它基于JavaScript的一个子集,易于人阅读和编写,同时也易于机器解析和生成。在客户端与服务端交互中,JSON起着至关重要的作用,因为它能够有效地...

    android app与服务器json交互

    在Android应用开发中,与服务器进行数据交互是一个关键环节,而JSON作为一种轻量级的数据交换格式,被广泛用于客户端和服务器之间的...通过分析和运行这些代码,可以更深入地理解Android App与服务器的JSON交互过程。

    Android与PHP通过JSON交互

    以上就是Android与PHP通过JSON交互的基本流程和关键点。通过这种方式,你可以实现Android客户端与PHP服务器的数据同步,比如用户登录、注册、获取列表等操作。在实际项目中,还需要考虑错误处理、安全策略(如JSONP...

    JS中Json对象

    ### JS中Json对象 #### JSON概述 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。JSON是基于JavaScript的一个子集,采用完全独立于编程语言的文本...

    多个JS+Json柱状图饼图折线图示例

    总结来说,"多个JS+Json柱状图饼图折线图示例"涉及到了前端开发中的数据可视化技术,包括JavaScript的图表库如Highcharts、Google Charts,以及JSON数据的处理和前后端交互。通过学习这些示例,开发者可以提升数据...

    河南省省市地图js和json文件

    总的来说,“河南省省市地图js和json文件”是利用JavaScript和JSON进行地图数据展示的一个实例,适用于需要展示河南省地图信息的Web应用。开发者可以通过学习和理解这些文件,结合Echarts等工具,创建出交互性强、...

    java json文档和示例

    本篇文章将详细介绍Java与JSON的交互,并提供相关示例。 一、JSON简介 JSON是一种独立于语言的数据格式,它的结构非常直观,主要由键值对(key-value pairs)组成,支持数组和对象。JSON的数据类型包括字符串...

    Django与JS交互的示例代码

    总之,Django和JavaScript之间的交互使得后端处理逻辑与前端展示动态化成为可能。理解如何传递和处理数据是构建交互式Web应用程序的关键技能。通过Ajax请求和在视图中直接渲染数据,开发者可以灵活地设计用户界面,...

    json数据jquery异步示例

    JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。它基于JavaScript的一个子集,通常用于在客户端(如浏览器)与服务器之间进行数据传输,特别是在AJAX...

    struts2与Ext4.0的json交互

    这篇博客文章“Struts2与Ext4.0的json交互”可能会探讨如何在Struts2中配置和使用JSON来与前端的Ext4.0框架进行通信。 首先,我们来看Struts2中的JSON插件。这个插件允许我们在Action类中直接返回JSON对象,无需...

    asp 处理json 示例

    ASP(Active Server Pages)是一种微软开发的服务器端脚本环境,用于创建动态网页或Web应用程序。在本示例中,我们将探讨如何使用ASP来处理...在ASP与JSON的交互中,熟练掌握这些技巧将大大提升你的Web应用开发能力。

    echarts 官方示例 json文件

    总的来说,ECharts 的官方示例 JSON 文件是学习和掌握 ECharts 图表配置、数据处理和交互设计的重要资源。通过深入研究这些文件,开发者可以熟练地运用 ECharts 实现各种复杂的数据可视化效果。

    edoJs与.net交互(json)

    7. **安全与性能**:在使用edoJs和.NET进行JSON交互时,应考虑安全因素,如防止XSS(跨站脚本攻击)和CSRF(跨站请求伪造)等。同时,为了优化性能,可以采用GZIP压缩、缓存策略等技术减少数据传输量和提高通信效率...

    山东省省市地图js和json文件

    山东省省市地图js和json文件是用于在Web应用中展示山东省各级行政区域地图的资源集合。这个压缩包包含的文件主要用于Echarts这样的数据可视化库,它能够帮助开发者在网页上绘制出详细、精确的地理信息图表。以下是...

    贵州省省市地图js和json文件

    在这个项目中,ECharts很可能是用来展示和操作地图的主要工具,通过JavaScript API与地图js和json文件进行交互,生成可交互的省级和市级地图。 至于压缩包子文件的文件名称列表只给出了“贵州省”,这可能意味着...

Global site tag (gtag.js) - Google Analytics