背景:XML曾经是互联网传输结构化数据的事实标准,但XML过于繁琐、冗长,而且解析麻烦,同XML数据结构要解析成DOM文档而且从中提取数据极为麻烦相比,JSON可以解析为JavaScript对象的优势极其明显。相比之下,JOSN是在JavaScript中读写结构化数据更好的方式,可以把JSON字符串直接传给eval(),而且不必创建DOM对象。JSON是一种数据格式,很多编程语言都有针对JOSN的解析器和序列化器。
一.JSON为JavaScript子集,可以使用eval解析JSON字符串,并返回JS对象/JS数组
var data = [ {name: "小明", sex:1, age: 30}, {name: "李雷", sex:0, age: 20}, {name: "熊二", sex:1, age: 30} ]; //data对象的JSON字符串表示形式 var dataJSONText = "[{‘name‘: ‘小明‘, ‘sex‘:1, ‘age‘: 30},{‘name‘: ‘李雷‘, ‘sex‘:0, ‘age‘: 20},{‘name‘: ‘熊二‘, ‘sex‘:1, ‘age‘: 30}]"; console.log(eval("("+dataJSONText+")"));//即为data对象
需要注意的是对象在JSON字符串中表现形式的差异性(对象的属性必须加双引号,这在JSON中是必须的!)
//JavaScript对象在JSON中的表示形式: var person = { name:"Nicholas", age:29 }; //JSON表示上述对象: { "name":"Nicholas", "age":29 }
二.JSON虽然为JavaScript子集,但还是具有些差异性
- 1.JSON不支持JavaScript中的特殊值undefined,但支持null
- 2.JSON不支持变量、函数或对象实例
三.全局JSON对象
早期使用eval()函数进行JSON字符串的解析,后来ECMAScript5对解析JSON进行规范,定义了全局对象JSON,现在的浏览器基本都支持这个对象。
JSON对象存在两种方法:
- JSON.stringify()序列化js对象为JSON字符串
JSON.parse()将JSON字符串解析为JS对象
例1.基本应用:
var data = [ {name: "小明", sex:1, age: 30}, {name: "李雷", sex:0, age: 20}, {name: "熊二", sex:1, age: 30} ]; //1.js对象序列化为json字符串 var str_json = JSON.stringify(data); //2.json字符串解析为原生js对象 var data_copy = JSON.parse(str_json);
四.JSON.stringify序列化
JSON.stringify()还可以接收另外两个参数:第一个参数是过滤器、第二个参数是选项(是否在JSON字符串中保留缩进)
1.第一个参数是过滤器:
测试数据1:
//json对象转js对象,右侧为json对象 var data=[ { "LBLCN": "事项", "FTYPE": "options", "TOOLTIP": "请选择事项", "REQD": false, "EDIT": "EVERYONE", "ITMS": [ { "VAL": "选项 1" }, { "VAL": "选项 2" }, { "VAL": "选项 3" } ], "DEF": "" }, { "LBLCN": "明细子表", "FTYPE": "detailTable", "FIELDS": [ { "LBLCN": "多行文本", "FTYPE": "textarea", "TOOLTIP": "", "REQD": false, "EDIT": "EVERYONE" }, { "LBLCN": "事项", "FTYPE": "options", "TOOLTIP": "请选择事项", "REQD": false, "EDIT": "EVERYONE", "ITMS": [ { "VAL": "选项 1" }, { "VAL": "选项 2" }, { "VAL": "选项 3" } ], "DEF": "" } ], "SCU": "pub" }]
过滤器是数组:
例2.
//此时也要使VAL属性对应的上级属性ITMS也要显示,否则VAL显示不出来 console.log(JSON.stringify(data,["VAL","FTYPE"])); //上级属性ITMS和下级属性VAL的先后顺序不会对过滤产生影响 console.log(JSON.stringify(data,["ITMS","VAL","FTYPE"])); console.log(JSON.stringify(data,["VAL","ITMS","FTYPE"])); //同级属性FTYPE和ITMS的先后顺序,会影响过滤结果的先后顺序 console.log(JSON.stringify(data,["FTYPE","VAL","ITMS"]));
测试数据2:
var book = { title:"Professional JavaScript", authors:[ "Nicholas C. Zakas" ], edition:3, year:2011 };
过滤器是函数:
例3.
var jsonText = JSON.stringify(book, function(key, value) { switch (key) { case "authors": return value.join(","); //将数组连接成一个字符串 case "year": return 5000; case "edition": return undefined; //通过返回undefined删除该属性 default: return value; //其他属性正常序列化 } } ); console.log(jsonText);//{"title":"Professional JavaScript","authors":"Nicholas C. Zakas","year":5000}
函数参数为属性名(key)和属性值,根据属性名可以知道如何处理序列化中的属性,并且属性名只能是字符串。注意:当并非键值对结构时,键名可以是空字符串!(实际上第一次调用函数过滤器,传入的键是空字符串,而值是book对象!)
例4.
var data = { "LBLCN": "事项", "FTYPE": "options", "TOOLTIP": "请选择事项", "REQD": false, "EDIT": "EVERYONE", "ITMS": [ "选项 1", "选项 2", "选项 3" ], "DEF": "" } var dataText = JSON.stringify(data, function(key, value) { switch (key) { case "ITMS": { var f = []; //js for/in for (i in value) { f.push({ "VAL": value[i] }); } return f; } case "VAL": return value + "test"; default: return value; } } , 4); console.log(dataText);
过滤原则:要序列化对象中的每一个对象都要经过过滤器函数(即使是转换后的对象,其属性和值也都要经过过滤)
2.第二个参数为字符串缩进
例4.
var book = { title:"Professional JavaScript", authors:[ "Nicholas C. Zakas" ], edition:3, year:2011 }; jsonText = JSON.stringify(book,null,4);//使得JSON字符串包含缩进空格和换行符,增强可读性 jsonText = JSON.stringify(book,null,"--");//"--"作为缩进符
五.toJSON
若JSON.stringify()还无法满足对某些对象自定义序列化的需求,可通过每个对象可以自定义toJSON方法,实现自己的序列化方式,toJSON作为函数过滤器的补充。
例5.
//Date 有自己的toJSON方法,返回值为字符串。故该对象将被序列化为一个简单字符串而非对象 var date = new Date(); console.log(date.toJSON());//2015-09-12T09:03:00.318Z
重难点:序列化对象的顺序(1.对象有自身的toJSON方法2.JSON.stringify()有过滤函数)
例6.
var person = { age:4, weight:"60kg", toJSON:function(){ return { height:"1.8m" } } }; var personText = JSON.stringify(person,function(key,value){ switch(key){ case "height": return value+" sss"; default: return value; }; }); console.log(personText);//{"height":"1.8m sss"}
顺序是:先调用对象自身的toJSON方法进行序列化2.如果有过滤函数的话,再使用步骤1返回的对象,通过过滤函数进行序列化
六.JSON.parse
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); console.log(new Date());