1

写这篇文章的缘由

你了解JSON嘛?JSON是JavaScript中对象嘛?JSON可以存储function对象嘛?JSON的本质是什么呢?JSON能写注释嘛?
如果你都能答上来,那恭喜你,你对JSON了解的很测底,如果你有写不太明白,哪有必要和我一起来探讨JSON

我之前对JSON的概念也是一知半解,常常和JavaScript的Object对象混淆,所以就导致了很多种种的错误,特别是在研究NodeJS中,有一个叫package.json的文件专门用来存储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的语法介绍

常见JSON数据结构有两种形式,其分别是:

  • “名称/值”对的集合,类似JavaScript中的对象。
  • 值的有序列表(An ordered list of values)。在大部分语言中,它被理解为数组(array)。

首先来看第一种情况:对象是一个无序的“‘名称/值’对”集合。一个对象以“{”(左括号)开始,“}”(右括号)结束。每个“名称”后跟一个“:”(冒号);“‘名称/值’ 对”之间使用“,”(逗号)分隔。

object.gif

这和JavaScript中的对象字面量比较类似,但是本质上还是有些区别的。比如对象中的名称(或者称为key)是必须用双引号括起来的。单引号都不行,更别说忽略它了,虽然JavaScript中的对象中的名称值常常忽略双引号。比如

{
    name : 'test',
    age  : 123,
    success : function(){
        //todo
    }
}

则在JSON中是行不通的。除了"名称(key)"值有限制外,对象中的"值(value)"也做了限制,比如在JavaScript中的对象字面量中的值可以随便赋值,不管是字符串、数组、函数、整形都是可以的。JSON中的取值可以是双引号括起来的字符串(string)、数值(number)、true、false、 null、对象(object)或者数组(array),
value.gif

除此之外,这些值以外都会被解析出问题,像刚才头中提到的,如果给JSON的值赋值一个function是一个错误的行为。

接下来,看看值的有序列表(或者称为数组),数组是值的有序列表,一个数组以“[”(左中括号)开始,“]”(右中括号)结束。值之间使用“,”(逗号)分隔,并且值的限制情况在上面中已经提到。

array.gif

差不多把语法介绍完了,总结一下,JSON其本质是一串有意义的字符串数据交互格式。呵呵,不知道我定义的正不正确。

JavaScript语言中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的序列化和解析,其分别是stringfyparse.让我们分别来看看它们的用法。

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中对象里面的keyvalue值。示例如下:

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中文官网


两仪
9.6k 声望729 粉丝

向上努力、不卑不亢、两仪相生