JSON就是一种数据格式,和XML一样,都是一种结构化类型的数据表示方式。很多编程语言都可以对JSON格式的数据进行解析和序列化。
一 JSON语法
JSON 格式支持三种语法值:简单值,数组,对象
JSON格式的数据,其实就是一段字符串。
简单值:
直接是数值型数据,字符串,null,布尔值,但是不知此JS中独有的undefined类型的值。下面的代码直接进行加载,看是否报错
<span style="font-size:18px;"> 100
true;
//abc;//报错了,当成了变量来处理
"acd";//正确,用双引号括起来了,当做是JSON格式的数据
null;
undefined; //不支持</span>
数组:
JSON格式的数组表示方法,相比普通的数组字面量方式,少了赋值符号和分号
<span style="font-size:18px;">JavaScript 数组字面量表示法:
var box = [100, 'Lee', true];
而 JSON 中的数组表示法同样没有变量赋值和分号:
[100, "Lee", true]</span>
对象:
JSON格式的数据中,对象的表示方法相对与JS中对象的字面量的区别是:没有赋值符号,键值对中将键和值都用引号括起来,最好是双引号。如果在JS文件中要不报错,就必须写在一行上面,并且用引号括起来。若写在单独的JSON文件中则不需要
<span style="font-size:18px;"> //JS 中对象的字面量表示方法这种带有赋值符号的对象,不是JSON格式的数据
var box = {
name:"abc",
age:22
}
//JSON 格式中的对象形式如下,键值对都是用引号括起来的,最好是双引号,但是下面这个同样会报错
{
"name":"acd",
"age":23
}
//JSON 格式的对象表示形式,JSON格式是一个字符串,故要用引号括起来
'{"name" : "abc","age" : 23,"height" : 134}'</span>
最常用语法:
最常用的一种JSON数据格式是数组+对象,一个数组中存放N个元素,每一个元素又是一个对象<span style="font-size:18px;">//最常用的JSON格式的表示方法,是数组对象表示法:而且这种写法还不会报错
[
{
"title":"one",
"age":23,
"height":178
},
{
"title":"two",
"age":23,
"height":177
},
{
"title":"three",
"age":24,
"height":176
}
]</span>
二 解析JSON数据
一般情况下,我们可以把 JSON 结构数据保存到一个文本文件里,然后通过XMLHttpRequest 对象去加载它,得到这串结构数据字符串。模拟加载 JSON 文本文件的数据,并且赋值给变量:
<span style="font-size:18px;">var box = '[{"name" : "a","age" : 1},{"name" : "b","age" : 2}]';</span>
这短代码模拟了 var box = load('demo.json');赋值过程。 因为通过 load 加载的文本文件,不管内容是什么,都必须是字符串。所以两边要加上双引号。当加载了JSON格式的数据后,需要对其解析成原声的JS代码才能够使用它。
eval()方法解析:
通过eval()方法可以执行一段字符串的JS代码,同样也就能够解析JSON格式的字符串,但是解析的时候很不安全,因为字符串里面可能会执行一些恶意代码
<span style="font-size:18px;"> var box='[{"title":"one","age":22},{"title":"two","age":35}]';
alert(box); //JSON 字符串
var json = eval(box); //用eval()方法来解析字符串
alert(json); //[object Object],[object Object] 得到原声的JS代码
alert(json instanceof Array); //true 解析成功后本来就是字符串套数组
alert(json[0]);
alert(json[0].title); //one
alert(json[1].age); //35</span>
全局对象JSON来解析:
全局对象json来进行解析的时候,对浏览器的版本有一定的要求,IE7-就不支持这种解析方式,对于不支持的浏览器也可以通过一个开源库 json.js 来模拟执行,里面就自定义了一个JSON对象【json.js】。全局解析的时候通过JSON对象提供的方法parse()来完成。
直接解析:
直接解析的时候,只是传递一个JSON格式的字符串或者子符文本即可,返回的是原JS代码
<span style="font-size:18px;"> var box='[{"title":"one","age":22},{"title":"two","age":35}]';
var json = JSON.parse(box);
alert(typeof json); //object
alert(json); //[object Object],[object Object]
alert(json[0].title); //one 解析之后的值
alert(json[1].age); //35</span>
接收第二个参数:
第二个参数,是一个函数,可以对解析后的值进行过滤,返回自己想要的值,两个参数代表的是键值对的键和值,对应字典
<span style="font-size:18px;"> var box='[{"title":"one","age":22},{"title":"two","age":35}]';
var json = JSON.parse(box,function(key,value){ //参数名可以改变
if(key == "title"){ //判断关键字是否是"title"
return "my is "+value;
}else if(key== "age"){ //
return "age="+value; //这里面可以运算
}else {
return value; //此处不能够做加法元算,会出问题
}
});
alert(json);
alert(json[0].title); //my is one
alert(json[1].title); //my is two
alert(json[0].age); //age=22
alert(json[1].age); //age=35</span>
三 序列化JSON数据
序列化JSON格式的数据是通过JSON对象提供的方法,JSON.stringify();同样可以接收多个参数,参数一为待解析的字符串,参数二位解析过滤条件,参数三位缩进字符数
原生的JS代码:
<span style="font-size:18px;"> var box=[{title:"one",age:22},{title:"two",age:35}];
alert(box[0].age); //22</span>
接收一个参数,普通的序列化:
<span style="font-size:18px;">var box=[{title:"one",age:22},{title:"two",age:35}];
var json = JSON.stringify(box);
alert(json instanceof String); //false
alert(typeof json); //string
//已经被序列化,对象中的键加上了双引号,而且单引号也变成了双引号
alert(json); //[{"title":"one","age":22},{"title":"two","age":35}] </span>
传递第二个参数,进行条件过滤:
参数二传递一个方法:
方法中的参数和解析JSON数据中的参数是一样的,两个参数,对应键和值
<span style="font-size:18px;"> var box=[{title:"one",age:22},{title:"two",age:35}];
var json = JSON.stringify(box,function(key,value){
if(key == "title"){
return "name:"+value;
}else if(key == "age"){
return "age:"+value;
}else{ //必须要添加这样一个else,否则序列化就不成功
return value;
}
})
//传递一个方法,改变值,将会序列化了每一个键值对
alert(json);//[{"title":"name:one","age":"age:22","height":188},{"title":"name:two","age":"age:35","heigth":199}]
</span>
参数二传递一个数组:
里面传递要进行序列化的键名,序列化的结果就是只是序列化数组中传递的键名的键值对
<span style="font-size:18px;"> var box=[{title:"one",age:22,height:188},{title:"two",age:35,heigth:199}];
var json = JSON.stringify(box,["title","age"]);
//上面传递一个数组,结果只是序列化了两个参数
alert(json); //[{"title":"one","age":22},{"title":"two","age":35}]</span>
在源JS代码中添加一个方法 toJSON:
这个方法,主要是在序列化的时候得到要序列化的内容,它的返回结果就是被序列化的内容,添加了这个方法后,对象中的其它属性字段都不会被序列化,除非在这个方法中写明了要序列的字段,而且添加了这个方法后,序列化的时候传递的第二个参数是不起作用的。
<span style="font-size:18px;"> var box=[
{
"title":"one",
"age":22,
"height":144,
toJSON:function(){ //方法名必须为toJSON,如果不是这个名称,也不会序列化这个方法
return this.title+this.height;
}
},
{
"title":"two",
"age":23,
"height":166,
toJSON:function(){
return this.title+this.height;
}
},
{
"title":"three",
"age":24,
"height":178,
toJSON:function(){
return this.title+this.height;
}
}
]</span>
<span style="font-size:18px;"> var json = JSON.stringify(box)
//在元数据中添加了一个 toJSON 方法,就只是序列化toJSON中执行的结果,方法名必须为toJSON
alert(json); //["one144","two166","three178"]
var json = JSON.stringify(box,["title"])
//有了toJSON方法,再传递一个参数就不起作用了
alert(json); //["one144","two166","three178"]</span>
参数三:控制格式
这个参数表示是否在 JSON 字符串中保留缩进,可以传递一个整形数据,也可以传递其它的符号,比如:*、-等
<span style="font-size:18px;"> var box=[{title:"one",age:22,height:188},{title:"two",age:35,heigth:199}];
var json = JSON.stringify(box,["title","age"],4);
//序列化的结果中,按照标准格式输出,<span style="color:#ff0000;">执行换行</span>,数字代表每一行相对于上一行应该缩进的距离
alert(json); //[{"title":"one","age":22},{"title":"two","age":35}]</span>
第三个参数传递字符的结果:
<span style="font-size:18px;"> var box=[{title:"one",age:22,height:188},{title:"two",age:35,heigth:199}];
var json = JSON.stringify(box,["title","age"],"--");
//用字符串同样的,只是前面用了一个--来标记:</span><span style="color: rgb(255, 0, 0); font-family: Arial, Helvetica, sans-serif; font-size: 18px;">打印的第三行格式为</span><span style="color: rgb(255, 0, 0); font-family: Arial, Helvetica, sans-serif;">:----"title": "one",</span><span style="font-size:18px;">
alert(json); //[{"title":"one","age":22},{"title":"two","age":35}]</span>
<span style="font-size:18px;"> var box=[{title:"one",age:22,height:188},{title:"two",age:35,heigth:199}];
var json = JSON.stringify(box,["title","age"],"*-");
//也可以,<span style="color:#ff0000;">打印的第三行格式为:*-*-"title": "one",</span>
alert(json); //[{"title":"one","age":22},{"title":"two","age":35}]</span>
当第三个参数传递字符的时候,这些字符并不是序列化后的有效JSON数据,仅仅是一个缩进格式而已,也就是将缩进的空白用传递的字符来代替
如果不需要对数据进行过滤,但是又想缩进,那么第二个参数写null即可
<span style="font-size:18px;">var box=[{title:"one",age:22,height:188},{title:"two",age:35,heigth:199}];
var json = JSON.stringify(box,null,"*-");
//第三行结果为:*-*-"title": "one",
alert(json); //[{"title":"one","age":22},{"title":"two","age":35}]</span>
从上可以看出,序列化的时候,toJSON方法的执行级别最高,然后是参数二和参数三