你了解JSON嘛?JSON
是JavaScript中对象嘛?JSON
可以存储function对象嘛?JSON
的本质是什么呢?JSON
能写注释嘛?
如果你都能答上来,那恭喜你,你对JSON
了解的很测底,如果你有写不太明白,哪有必要和我一起来探讨JSON
。
我之前对JSON
的概念也是一知半解,常常和JavaScript的Object对象混淆,所以就导致了很多种种的错误,特别是在研究NodeJS
中,有一个叫package.json的文件专门用来存储json格式的数据。如果你在这个文件里面写注释,或者存储函数,最终解析这个文件时就会报错。
然后自己查阅了些相关的资料,得出些结论。现在拿出来和大家分享一下,同时,假如文章中有纰漏的地方,大家可以帮我指点纠正下。
首先我们来看看官方是怎么描述JSON
的:JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。 易于人阅读和编写。同时也易于机器解析和生成。 它基于JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。 这些特性使JSON成为理想的数据交换语言。参考来源地址:http://www.json.org/json-zh.html。
官方的说法,也不是特别的明了,只说明了这是一种轻量级的数据交换格式,且基于JavaScript一个子集。这根本说明不了什么?不过我联想到了另外一种数据交换格式,那就是xml,这个格式特别在webService中被大量使用。xml是什么呢,其本质是一种DOM结构。对比一下,那json
的本质就是字符串了,不过这个字符串不是不同的字符串,它有一些列的语法和结构。下面我们就介绍下其语法。
常见JSON数据结构有两种形式,其分别是:
首先来看第一种情况:对象是一个无序的“‘名称/值’对”集合。一个对象以“{”(左括号)开始,“}”(右括号)结束。每个“名称”后跟一个“:”(冒号);“‘名称/值’ 对”之间使用“,”(逗号)分隔。
这和JavaScript中的对象字面量比较类似,但是本质上还是有些区别的。比如对象中的名称(或者称为key)是必须用双引号括起来的。单引号都不行,更别说忽略它了,虽然JavaScript中的对象中的名称值常常忽略双引号。比如
{
name : 'test',
age : 123,
success : function(){
//todo
}
}
则在JSON中是行不通的。除了"名称(key)"值有限制外,对象中的"值(value)"也做了限制,比如在JavaScript中的对象字面量中的值可以随便赋值,不管是字符串、数组、函数、整形都是可以的。JSON中的取值可以是双引号括起来的字符串(string)、数值(number)、true、false、 null、对象(object)或者数组(array),
除此之外,这些值以外都会被解析出问题,像刚才头中提到的,如果给JSON的值赋值一个function
是一个错误的行为。
接下来,看看值的有序列表(或者称为数组),数组是值的有序列表,一个数组以“[”(左中括号)开始,“]”(右中括号)结束。值之间使用“,”(逗号)分隔,并且值的限制情况在上面中已经提到。
差不多把语法介绍完了,总结一下,JSON
其本质是一串有意义的字符串数据交互格式。呵呵,不知道我定义的正不正确。
在JavaScript中经常是要对JSON进行处理的,比如提交一个数据前常常需要对其进行序列化处理,从后来拉过来的JSON数据,我们经常要对它进行解析然后得到一个JavaScript对象。可能由于大家经常使用一些JavaScript类库,这些库对JSON的操作做了封装,所以造成一种现象,那就是我们只会用,对齐本质,我们了解甚少。现在我们就抛开类库,了解其底层的本质。
早期的JSON解析器通过JavaScript中eval()函数来解析的。直到ECMA5对齐进行了规范,并且定义了一个全局的JSON对象用来对JSON进行解析和序列化。支持JSON这个全局对象的浏览器包括IE8+、FF3.5+、Safari4+、Chrome和Opera10.5+。对于不支持这个对象的浏览器比如IE6、IE7怎么做处理呢?
不用担心,JSON的发明者早就帮我们实现了兼容的代码,其地址为:https://github.com/douglascrockford/JSON-js。对于不支持原生的JSON对象的。我们可以引入这段代码解决兼容性的问题。
JSON有两个主要方法,用来解决JSON的序列化和解析,其分别是stringfy
和parse
.让我们分别来看看它们的用法。
ECMA5定义的标准接口如下所示:
/**
@param {*} value
@param {Function} [replacer]
@param {Number|String} [space]
@static
*/
JSON.stringify = function(value,replacer,space) {};
其中对一个参数是必须滴,而且是我们要进行序列化的对象。示例代码如下所示:
var obj = {
name : 'hello',
age : 18
}
var jsonText = JSON.stringify(obj) //输出:{"name":"hello","age":18}
第二个参数是可选项,可以是函数或者是数组。如果是数组,那么数组中指定是过滤项,以上面例子为例,进行如下调用:
var jsonText = JSON.stringify(obj,["name"]) //输出: {"name":"hello"}
如果是函数的话,回调函数里面的参数对应Javascript中对象里面的key
和value
值。示例如下:
var jsonText = JSON.stringify(obj,function(key,value){
switch(key) {
case "name": return value+" json";
case "age" : return 20;
default : return value;
}
});
//输出 {"name":"hello json","age":20}
第三个参数也是可选的。用来进行字符串缩进,示例如下:
var jsonText = JSON.stringify(obj,null,4); //按4个空格缩进
//输出的结果不再是单行,而是下面的形式:
{
"name" : "hello",
"age" : 18
}
除了可以设置数字外,还可以用字符设置缩进,有兴趣大家可以尝试一下。
ECMA5对parse
接口的定义如下:
/**
@param {string} jsonString
@param {Function} [reviver]
@static
*/
JSON.parse = function(jsonString,reviver) {};
该方法接受两个参数,其中第二个参数是可选的。
第一个参数的作用是待转换的JSON字符串。比如我们可以将上面的jsonText通过parse还原成原来的Javascript对象。
var obj = JSON.parse(jsonText); //obj为JavaScript对象。
第二个参数是一个函数,用来更加细微的控制转换过程。它接受两个参数,分别对应着JSON数据的键值对。调用示例如下:
var obj = JSON.parse(jsonText,function(key,value){
//todo
});
JSON中文官网