js编写jsonapi(JSON对象-Web前端开发之JavaScript-零点程序员-王唯)
js编写jsonapi(JSON对象-Web前端开发之JavaScript-零点程序员-王唯)'{"name":"wangwei" "sex":true "age":18 "company":{"name":"零点网络" "url":"https://www.zeronetwork.cn"}}'数组:JSON使用Javascript中的数组字面量语法来表示数组,数组的值也可以是任意类型,即可以是简单值、对象或数组,如:{ "name": "wangwei" "sex": true "age": 18 "company": { "name": "零点网络"
本内容是《Web前端开发之Javascript视频》的课件,请配合大师哥《Javascript》视频课程学习。
由于在Javascript中操作XML存在严重的跨浏览器问题,且从XML结构中提取数据也要涉及遍历DOM文档,Douglas Crockford(道格拉斯·克罗克福德)发明了一种名为json(JavaScript Object Notation,JavaScript对象表示法)的数据格式,用以避免使用XML数据的麻烦;
JSON是Javascript语法中的一个子集,利用了Javascript中的一些模式来表示结构化数据,特别是对象和数组字面量;使用JSON能够创建与XML相同的数据结构,它是一种轻量级的数据格式,可以简化表示复杂数据结构的工作量;如:
{
"name": "wangwei"
"title": "Engineer"
"sex": true
"age": 18
}
JSON并不从属于Javascript,而且并不是只有Javascript才使用JSON,因为它只是一种数据格式,所以很多开发语言都有针对JSON的解析器和序列化器
JSON语法:
简单值:
使用与Javascript相似的语法,在JSON中可以使用字符串、数值、布尔值和null;但JSON不支持Javascript中的特殊值undefined;
JSON字符串与Javascript字符串最大的区别是,JSON字符串中的属性名和属性值必须使用双引号,但属性值如果是Boolean或Number类型的可以不用加双引号,如:
// var data = '{"name":"wangwei" "title":"engineer" "sex":true "age":18}';
// 改成单引号,抛出Uncaught SyntaxError
var data = "{'name':'wangwei'}";
console.log(JSON.parse(data));
在Javascript中,不要求给对象的属性加引号,但在JSON字符串中未加引号的属性被视为一个语法错误;
在JSON中没有变量声明,在末尾也不需要分号
对象:JSON的值可以是简单值,也可以是复杂类型,如:
{
"name": "wangwei"
"sex": true
"age": 18
"company": {
"name": "零点网络"
"url": "https://www.zeronetwork.cn"
}
}
字符串形式:
'{"name":"wangwei" "sex":true "age":18 "company":{"name":"零点网络" "url":"https://www.zeronetwork.cn"}}'
数组:
JSON使用Javascript中的数组字面量语法来表示数组,数组的值也可以是任意类型,即可以是简单值、对象或数组,如:
var values = ["wangwei" true 18]; // javascript
["wangwei" true 18] // JSON
字符串表示:
'["wangwei" true 18]'
如:
{
"name": "WangWei"
"sex": true
"age": 18
"company": {
"name": "零点网络"
"url": "https://www.zeronetwork.cn"
}
"friends": ["JingJing" "Juanzi" "daguo"]
}
字符串表示:
var data = '{"name":"wangwei" "sex":true "age":18 "company":{"name":"零点网络" "url":"https://www.zeronetwork.cn"} "friends":["JingJing" "Juanzi" "daguo"]}';
console.log(JSON.parse(data));
把数组和对象结合起来,就可以构成更为复杂的数据集合,如:
[
{
"name": "WangWei"
"sex": true
"age": 18
"company": {
"name": "零点网络"
"url": "https://www.zeronetwork.cn"
}
"friends": ["JingJing" "Juanzi" "daguo"]
}
{
"name": "JingJing"
"sex": false
"age": 20
"company": {
"name": "零点培训"
"url": "https://edu.zeronetwork.cn"
}
"friends": ["wangwei" "Juanzi" "daguo"]
}
];
字符串表示:
var data = '[{"name":"WangWei" "sex":true "age":18 "company":{"name":"零点网络" "url":"https://www.zeronetwork.cn"} "friends":["JingJing" "Juanzi" "daguo"]} {"name":"JingJing" "sex":false "age":20 "company":{"name":"零点培训" "url":"https://edu.zeronetwork.cn"} "friends":["wangwei" "Juanzi" "daguo"]}]';
console.log(JSON.parse(data)); // Array
利用数组和对象,可以创造出各种各样的数据结构,这也是JSON最常用的数据结构;
JSON不支持变量、函数或对象实例;
序列化 (Serialization)及反序列化:
序列化是将对象的状态信息转换为可以存储或传输的形式的过程;在此期间,对象将其当前状态写入到临时或持久性存储区,之后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。
早期的JSON的实现原理:
JSON的设计意图是在服务器端构建格式化的数据,然后再将数据发送给浏览器;由于JSON在JavaScript中相当于对象和数组,因此JSON字符串可以传递给eval()函数,让其解析并返回一个对象或数组的实例,如:
var data = '[{"name": "wangwei" "sex": true "age": 18} {"name": "JingJing" "sex": false "age": 20}]';
var jsonObj = eval('(' data ')');
console.log(jsonObj);
console.log(jsonObj[0].name);
解析和序列化:
可以把JSON数据结构解析为Javascript对象;
由于JSON结构是被转换为Javascript对象,所以访问这种数据比XML更方便、解析速度更快,因此JSON成了替代XML的数据格式,成为了Web开发中交换数据的事实标准;
JSON对象有两个方法:stringify()和parse(),分别用于把Javascript对象序列化为JSON字符串和把JSON字符串解析为原生Javascript值(对象);
JSON.stringify(value[ replacer [ space]])方法:
用于将一个JavaScript对象或值转换为 JSON 字符串;参数value为将要序列化成一个JSON字符串的值或对象;参数replacer为一个可选的过滤器;可选参数space指定了如何缩进;返回值是一个JSON字符串,如:
console.log(JSON.stringify({})); // '{}'
console.log(JSON.stringify(true)); // 'true'
console.log(JSON.stringify("wangwei")); // '"wangwei"'
console.log(JSON.stringify([1 "false" false]));// '[1 "false" false]'
console.log(JSON.stringify({ x: 5 y: 6 })); // {"x":5 "y":6}
console.log(JSON.stringify([new Number(3) new String('false') new Boolean(false)]));
// [3 "false" false]
var person = {
name: "wangwei"
sex: true
age: 18
company: {
name: "零点网络"
url: "https://www.zeronetwork.cn"
}
}
var jsonText = JSON.stringify(person);
console.log(person);
console.log(jsonText);
布尔值、数字、字符串的包装对象在序列化过程中会自动转换成对应的原始值;
如果有前导零的话,会忽略该前导零;
非数组对象的属性不能保证以特定的顺序出现在序列化后的字符串中;
默认情况下,JSON.stringify()输出的JSON字符串不包含任何空格字符或缩进;
序列化对象时,所有函数及原型成员都会被忽略,不会体现在结果上;此外,值为undefined的任何属性也都会被跳过,如:
var person = {
name: "wangwei"
sex: true
age: 18
smoking: Function(){}
marry: undefined
}
var jsonText = JSON.stringify(person);
console.log(person);
// {"name":"wangwei" "sex":true "age":18}
// smoking及marry被忽略了
console.log(jsonText);
函数、undefined被单独转换时,会返回undefined,如:
console.log(JSON.stringify(function(){})); // undefined
console.log(JSON.stringify(undefined)); // undefined
值为NaN、Infinity和-Infinity序列化的结果是null;而日期对象序列化的结果是ISO格式的日期字符串(与Date.toJSON()方法是一致的),但JSON.parse()会保留它们的字符串的形态,不会将它们还原为原始日期对象;
var d = new Date(2021 7 13 15 6 8);
console.log(JSON.stringify(d));
// "2021-08-13T07:06:08.000Z"
console.log(d.toJSON());
// 2021-08-13T07:06:08.000Z
var person = {
"name": "wangwei"
"sex": true
"age": 18
"isNaN": NaN
"isInfinity": Infinity
"birthday": (new Date())
};
var jsonText = JSON.stringify(person);
console.log(jsonText);
var person = JSON.parse(jsonText);
console.log(person);
JSON.stringify()只能序列化对象可枚举的自有属性,如:
function Person(){
this.name = "wangwei";
this.sex = true;
}
Person.prototype = {
constructor: Person
age: 18
};
var person = new Person();
person.job = "engineer";
Object.defineProperty(person "marry" {
value: true
// enumerable: true // [ɪˈnjuːməˈeɪbl]
enumerable: false
});
console.log(person);
for(var prop in person){
console.log("person." prop "=" person[prop]);
}
console.log(Object.keys(person));
console.log(JSON.stringify(person));
序列化选项:
json.stringify(value[ replacer [ space]])方法的value参数是需要序列化的Javascript对象,replacer与space用于指定以不同的方式序列化Javascript对象,其中replacer是一个替换(过滤)器,其可以是一个数组,也可以是一个函数;space参数表示是否在JSON字符串中保留缩进;
单独或组合使用这两个参数,可以更全面深入的控制JSON的序列化结果;
replacer参数:
如果replacer是数组,那么JSON.stringify()的结果中将只包含数组中列出的属性,如:
var person = {
name: "wangwei"
sex: true
age: 18
friends: ["JingJing" "Juanzi"]
}
var jsonText = JSON.stringify(person ["name" "age"]);
console.log(jsonText); // {"name":"wangwei" "age":18}
如果过滤器数组中指定的属性在需要序列化的对象中不存在,会被忽略;
如果参数replacer是一个函数,则在序列化过程中,被序列化对象的每个属性都会经过该函数的转换和处理;该函数会在序列化的对象的作用域中运行,其参数是相应的属性名key(键)和value属性值,返回值就是该属性的新值,如果函数返回了undefined,那么相应的属性会被忽略,如:
var jsonText = JSON.stringify(person function(key value){
switch(key){
case "name":
return "我的姓名:" value;
case "sex":
return value ? "男" : "女";
case "age":
return undefined;
case "friends":
return "朋友:" value.join(" ");
default:
return value;
}
});
// {"name":"我的姓名:wangwei" "sex":"男" "friends":"朋友:JingJing Juanzi"}
console.log(jsonText);
在switch语句中,一定要有default语句,以便其他属性值都能正常地出现在结果中;
并不是所有Javascript的值都可以使用JSON表示,如函数和undefined值无法通过JSON表示,包含它们的任何键默认都被移除,要改变这种默认的行为,就可以使用replacer函数,如:
var person = {
name: "wangwei"
sex: true
age: 18
friends: undefined
smoking: function(){}
}
var jsonText = JSON.stringify(person function(key value){
if (value instanceof Function) {
return "(function)";
}else if(value == undefined){
return "undefined";
}else{
return value;
}
});
// {"name":"wangwei" "sex":true "age":18 "friends":"undefined" "smoking":"(function)"}
console.log(jsonText);
replacer函数会遍历所有属性,但在第一次遍历时,传入的键是一个空字符串,而值就是需要序列化的对象,如:
var jsonText = JSON.stringify(person function(key value){
console.log(key ":" value);
return value;
});
// :[object Object]
// name:wangwei
// sex:true
// age:18
// friends:JingJing Juanzi
// 0:JingJing
// 1:Juanzi
因此,可以通过判断key是否是空字符串,从而决定如何操作,如:
var jsonNumber = {1:1 2:2 3:3 4:4 5:5};
var jsonText = JSON.stringify(jsonNumber function(key value){
console.log(key " = " value);
if (key == "") {
return value;
}
return value * 2;
});
console.log(jsonText);
如果处理的某个属性值是一个对象,则该函数会遍历序列化该对象,其遍历顺序是由外向内;如:
var person = {
name: "wangwei"
age: 18
friends: ["JingJing" "Juanzi"]
smoking: function(){}
company: {
name: "零点网络"
contact:{
tel: "01088886666"
address: "北京市朝阳区"
}
}
};
var jsonText = JSON.stringify(person function(key value){
console.log(key ":" value);
return value;
});
console.log(jsonText);
不能用replacer返回undefined的方式,从数组中移除值,如若返回undefined或者一个函数,将会被null取代;如:
var arr = ["wangwei" "jingjing" "juanzi"];
var jsonText = JSON.stringify(arr function(key value){
console.log(key " = " value);
if (key == "") {
return value;
}
if (key == 1) {
return undefined;
}
if (key == 2) {
return function(){};
}
return value;
});
console.log(jsonText);
space参数:
默认情况下,stringify()返回未经缩进的JSON字符串;json.stringify()方法的的第三个参数space用于控制结果中的缩进和空白符;如果参数是一个数值,则表示的是每个级别缩进的空格数,如:
var person = {
name: "wangwei"
sex: true
age: 18
friends: ["JingJing" "Juanzi"]
}
var jsonText = JSON.stringify(person null 4);
// {
// "name": "wangwei"
// "sex": true
// "age": 18
// "friends": [
// "JingJing"
// "Juanzi"
// ]
// }
console.log(jsonText);
其中结果字符串中插入了换行符以及缩进;只要传入有效的控制缩进的参数值,结果字符串就会包含换行符;
最大缩进空格数为10,如果大于10会被自动转换为10,值若小于1,则意味着没有空格;
如果缩进参数是一个字符串,则这个字符串将在JSON字符串中被用作缩进字符,如:
var jsonText = JSON.stringify(person null "--");
// {
// --"name": "wangwei"
// --"sex": true
// --"age": 18
// --"friends": [
// ----"JingJing"
// ----"Juanzi"
// --]
// }
console.log(jsonText);
在使用字符串的情况下,也可以将缩进字符设置为制表符,或者其它任意字符;同样的,缩进字符串不能超过10个字符长,如果超过10个,只取前10个;
toJSON()方法:
JSON.stringify()在某些时候还不能满足对某些对象进行自定义序列化的需求,在这种情况下,可以给对象定义toJSON()方法,返回其自身的JSON数据格式;
例如:原生Date对象有一个toJSON()方法,能够将Date对象自动转换成ISO8601日期字符串(与在Date对象上调用toISOString()的结果完全一样)如:
var d = new Date();
console.log(d.toJSON());
console.log(d.toISOString());
console.log(JSON.stringify(d));
可以为任何对象添加toJSON()方法,如:
var person = {
name: "wangwei"
sex: true
age: 18
friends: ["JingJing" "Juanzi"]
toJSON: function(){
return this.name;
}
}
var jsonText = JSON.stringify(person);
console.log(jsonText); // "wangwei"
可以让toJSON()方法返回任何值,例如可以让这个方法返回undefined,此时如果包含它的对象嵌入在另一个对象中,会导致它的值变成null,而如果它是顶级对象,结果就是undefined;
toJSON()方法可以作为replacer函数的补充,序列化该对象的顺序如下:
- 1.如果存在toJSON(),而且能通过它取得有效的值,则调用该方法,否则,返回对象本身;
- 2.如果提供了replacer参数,则应用这个函数,传入函数的值是第1步返回的值;
- 3.对第2步返回的每个值进行相应的序列化;
- 4.如果提供了space参数,则执行相应的格式化;
replacer函数中的this:
指向的就是当前级所对应的对象,如:
var jsonText = JSON.stringify(person function(key value){
console.log(key ":" value);
console.log(this);
return value;
} 4);
JSON.parse(text[ reviver])方法:
用来解析JSON字符串,返回一个由字符串描述构造出的JavaScript值或对象;参数text为要被解析成 JavaScript 值或对象的字符串;可选参数reviver是一个转换器函数,用以在返回之前对所得到的值执行变换(操作),如:
console.log(JSON.parse('{}')); // {}
console.log(JSON.parse('true')); // true
console.log(JSON.parse('"wangwei"')); // "wangwei"
console.log(JSON.parse('[1 5 "false"]')); // [1 5 "false"]
console.log(JSON.parse('null')); // null
如果传给JSON.parse()的字符串不是有效的JSON字符串,该方法会抛出异常;另外,JSON字符串也不允许用逗号作为结尾;如:
JSON.parse("[1 2 3 4 ]");
JSON.parse('{"name":"wangwei" }');
解析选项:
parse()方法的reviver是一个可选的转换器函数,该函数将在每个键值对上调用,并以键key和值value作为参数,并且必须返回一个值,返回值将成为结果对象中与指定键关联的值,如:
var jsonText = '{"name":"wangwei" "sex":true "age":18 "friends":["JingJing" "Juanzi"]}';
var p = JSON.parse(jsonText function(key value){
switch(key){
case "age":
return value 1;
case "sex":
return undefined;
default:
return value;
}
});
console.log(p);
console.log(p.age);
如果针对某个键返回undefined,就可以从结果对象中移除该键;
在将日期字符串转换为Date对象时,经常要用到reviver还原函数,如:
var person = {
name: "wangwei"
sex: true
age: 18
birthday: new Date(2002 8 13)
}
var jsonText = JSON.stringify(person);
console.log(jsonText);
var newPerson = JSON.parse(jsonText function(key value){
if (key == "birthday") {
return new Date(value);
}else{
return value;
}
});
console.log(newPerson);
console.log(newPerson.birthday);
console.log(newPerson.birthday.getFullYear()); // 2002
如果没有指定reviver函数,会直接解析出JavaScript值或对象,如果指定了reviver函数,则在解析前会经过一次转换后,才将返回最终值;
在解析时,解析值本身以及它所包含的所有属性,会按照一定的顺序,即从最里层的属性开始,一级级往外,最终到达顶层,也就是解析值本身,按照这个顺序分别去调用reviver函数;
var obj = JSON.parse('{"1": 1 "2": 2 "3": {"4": 4 "5": {"6": 6}}}' function (k v) {
console.log(k); // 输出当前的属性名,从而得知遍历顺序是从内向外的,
// 最后一个属性名会是个空字符串,也就是最顶层
return v; // 返回原始属性值,相当于没有传递reviver参数。
}); // 1 2 4 6 5 3 ""
console.log(obj);
当遍历到最顶层的值(解析值)时,传入reviver函数的参数是一个空字符串 ""和当前的解析值,如:
var obj = JSON.parse('{"p": 5}' function (k v) {
if(k === '') return v; // 如果到了最顶层,则直接返回属性值,
return v * 2; // 否则将属性值变为原来的2倍。
});
console.log(obj); // {p:10}
reviver中的this:
在调用过程中,当前属性所属的对象会作为this值,当到达最顶层时,this值会是 {"": 修改过的解析值};
原生Javascript对象与JSON解析出来的对象,虽然具有相同的属性,但两者是完全不同的对象;
使用JSON.parse(JSON.stringify(obj)),可实现多维对象的深拷贝:
var person = {
name: "wangwei"
sex: true
age: 18
isUndefined: undefined
isInfinity: Infinity
birthday: (new Date())
smoking: function(str){console.log(this.name ":" str)}
friends: ["jingjing" "juanzi"]
company: {
name: "零点网络"
url: "https://www.zeronetwork.cn"
}
};
console.log(JSON.parse(JSON.stringify(person)));
undefined及函数会被忽略,但也可以使用序列化选项及解析选项自定义还原;
var jsonText = JSON.stringify(person function(key value){
var type = typeof value;
if (value == Infinity || type == "undefined" || type == "function") {
value = "[[" value "]]";
}
return value;
});
console.log(jsonText);
var person = JSON.parse(jsonText function(key value){
// 还原日期
var reg = /\d{4}. \d{1 2}. \d{1 2}/;
if (typeof value == "string" && reg.test(value)) {
value = new Date(value);
}
return value;
});
for(item in person){
// 还原undefined和function
var value = person[item];
var reg = /\[\[(.*)\]\]/;
if (typeof value == "string" && reg.test(value)) {
value = value.match(reg)[1];
person[item] = eval("(" value ")");
}
}
console.log(person);
person.smoking("吸烟");
//封装
function cloneJSON(source) {
var jsonText = JSON.stringify(person function(key value){
var type = typeof value;
if (value == Infinity || type == "undefined" || type == "function") {
value = "[[" value "]]";
}
return value;
});
var obj = JSON.parse(jsonText function(key value){
var reg = /\d{4}. \d{1 2}. \d{1 2}/;
if (typeof value == "string" && reg.test(value)) {
value = new Date(value);
}
return value;
});;
for(item in obj){
var value = obj[item];
var reg = /\[\[(.*)\]\]/;
if (typeof value == "string" && reg.test(value)) {
value = value.match(reg)[1];
obj[item] = eval("(" value ")");
}
}
return obj;
}
var p = cloneJSON(person);
console.log(person);
console.log(p);
兼容方案:
老版本的浏览器不支持JSON,例如IE7及以下不支持,但可以模仿原生JSON对象,如:
if (!window.JSON) {
window.JSON = {
parse: function(sJSON){
return eval('(' sJSON ')');
}
stringify: (function(){
var toString = Object.prototype.toString;
var isArray = Array.isArray || function(a){
return toString.call(a) === '[object Array]';
};
var escMap = {'"': '\\"' '\\': '\\\\' '\b': '\\b' '\f':'\\f' '\n': '\\n' '\r': '\\r' '\t': '\\t'};
var escFunc = function(m){
return escMap[m] || '\\u' (m.charCodeAt(0) 0x10000).toString(16).substr(1);
};
var escRE = /[\\"\u0000-\u001F\u2028\u2029]/g;
return function stringify(value){
if (value == null) {
return 'null';
}else if(typeof value === 'number'){
return isFinite(value) ? value.toString() : 'null';
}else if(typeof value === 'boolean'){
return value.toString();
}else if (typeof value === 'object') {
if (typeof value.toJSON === 'function') {
return stringify(value.toJSON());
}else if (isArray(value)) {
var res = '[';
for(var i=0; i<value.length; i ){
res = (i ? ' ' : '') stringify(value[i]);
}
return res ']';
}else if (toString.call(value) === '[object Object]') {
var tmp = [];
for(var k in value){
if (value.hasOwnProperty(k)) {
tmp.push(stringify(k) ":" stringify(value[k]));
}
}
return '{' tmp.join(' ') '}';
}
}
return '"' value.toString().replace(escRE escFunc) '"';
};
})()
};
}
// console.log(window.JSON);
var person = {
name: "wangwei"
sex: true
age: 18
intro: "全栈开发者:\u2028王唯\u2029零点\n程序\r员"
friends: ["jingjing" "juanzi" [1 2 3] {a:"a" b:"b" c:"c"}]
smoking: function(){}
company: {
name: "零点网络"
contact:{
tel: "01088886666"
address: "北京市朝阳区"
}
}
};
var jsonText = JSON.stringify(person);
console.log(jsonText);
var person = JSON.parse(jsonText);
console.log(person);
JSON2.js:
对于较早的浏览器不支持JSON,还可以使用Douglas Crockford自己维护的一个针对Javascript的JSON序列化器和解析器:https://github.com/duglascrockford/JSON-js,虽然它在旧版本的浏览器中,还是使用eval()函数进行对象的JSON数据结构求值,但对于不支持原生JSON解析的浏览器这是最佳的选择;
cycle.js:
该库包含两个函数,JSON.decycle和JSON.retrocycle;这使得在JSON中对循环结构可以序列化,并且解析它们;目前,ES5中的JSON对象是实现不了循环结构的对象的序列化,此时就可以使用这个库来实现;如:
var cycled = {
foo: {}
bar: {}
};
cycled.foo.bar = cycled.foo;
cycled.bar.foo = cycled.bar;
console.log(cycled); // 原始对象
var o = JSON.decycle(cycled); // 解除对象的循环引用
console.log(o);
var jsonText = JSON.stringify(o); // 序列化
console.log(jsonText);
var o = JSON.parse(jsonText); // 解析为无对象引用
console.log(o);
var obj = JSON.retrocycle(o); // 转换为对象引用
console.log(obj);
在Ajax中使用JSON:
在Ajax中,可以请求JSON数据,进而解析为JSON对象,如:
example.json:
{
"name": "wangwei"
"sex": true
"age": 18
"friends": ["JingJing" "Juanzi"]
}
JavaScript:
var xhr = new XMLHttpRequest();
xhr.onload = function(event){
var data = event.target.response;
var h2 = document.createElement("h2");
h2.innerText = data.name;
document.body.appendChild(h2);
var p = document.createElement("p");
p.innerText = "性别:" (data.sex ? "男" : "女") ",年龄:" data.name;
document.body.appendChild(p);
if (data.friends && data.friends instanceof Array) {
var span = document.createElement("span");
span.innerText = data.friends.join(" ");
p.appendChild(span);
}
}
xhr.open("GET" "example.json" true);
xhr.responseType = "json";
xhr.send(null);
示例:使用localStorage保存JSON序列化后的数据,如:
if (localStorage.getItem('screenObj')){
var restoredScreen = JSON.parse(localStorage.getItem('screenObj'));
console.log(restoredScreen);
}else{
var screenObj = {
screens : []
state : true
};
screenObj.screens.push({name:"screenB" width:650 height:350});
screenObj.screens.push({name:"screenC" width:750 height:120});
screenObj.screens.push({name:"screenA" width:450 height:250});
screenObj.screens.push({name:"screenD" width:1240 height:650});
localStorage.setItem('screenObj' JSON.stringify(screenObj));
}
示例:克隆对象、将对象序列化保存到SessionStorage中并读取;如:
var JSON_Serialize_FIX = {
PREFIX: "[[JSON_FUN_PREFIX_"
SUFFIX: "_JSON_FUN_SUFFIX]]"
};
function getSessionJSONItem(key type){
if(type)
key = key "_" type;
return JSON.parse(sessionStorage.getItem(key) function(key value){
if (typeof value == "string" &&
value.indexOf(JSON_Serialize_FIX.PREFIX) == 0 &&
value.indexOf(JSON_Serialize_FIX.SUFFIX) > 0) {
return eval("(" value.replace(JSON_Serialize_FIX.PREFIX "")
.replace(JSON_Serialize_FIX.SUFFIX "") ")");
}
return value;
}) || {};
}
function setSessionJSONItem(key obj type){
if(type)
key = key "_" type;
sessionStorage.setItem(key JSON.stringify(obj function(key value){
if (typeof value == 'function') {
return JSON_Serialize_FIX.PREFIX value.toString() JSON_Serialize_FIX.SUFFIX;
}
return value;
}));
}
function cloneJSON(obj){
var jsonText= JSON.stringify(obj function(key value){
if (typeof value === 'function') {
return JSON_Serialize_FIX.PREFIX value.toString() JSON_Serialize_FIX.SUFFIX;
}
return value;
});
return JSON.parse(jsonText function(key value){
if (typeof value === 'string' &&
value.indexOf(JSON_Serialize_FIX.PREFIX) == 0 &&
value.indexOf(JSON_Serialize_FIX.SUFFIX) > 0) {
return eval("(" value.replace(JSON_Serialize_FIX.PREFIX "")
.replace(JSON_Serialize_FIX.SUFFIX "") ")");
}
return value;
}) || {};
}
var person = {
name:"wangwei"
sex:true
age:18
smoking:function(){console.log("smoking")}
};
setSessionJSONItem("person" person "data");
console.log(getSessionJSONItem("person" "data"));
console.log(cloneJSON(person));
JSON使用场景:
JSON应用的场景比较多,如:
- 1.前后端数据传输;
- 2.Ajax异步访问数据;
- 3.RPC远程调用;
- 4.生成Token;
- 5.接口返回数据:
- 6.充当配置文件;
JSON与Excel:
示例:将json数据转为table数据再进行Excel导出;
<script>
function JSONToExcelConvertor(JSONData FileName Title){
var arrData = typeof JSONData != 'object' ? JSON.parse(JSONData) : JSONData;
if (Title) {
for(var i=0; i < arrData.length; i ){
var data = arrData[i];
for(var item in data){
if (!Title.hasOwnProperty(item)) {
delete data[item];
}
}
}
}
var excel = '<table>';
var row = '<tr>';
if (Title) {
for(var item in Title){
row = '<td>' Title[item] '</td>';
}
}else{
for(var item in arrData[0]){
row = '<td>' item '</td>';
}
}
excel = row '</tr>';
for(var i=0; i < arrData.length; i ){
var row = '<tr>';
for(var item in arrData[i]){
row = '<td>' arrData[i][item] '\t' '</td>';
}
excel = row '</tr>';
}
excel = '</table>';
var excelFile = "<html xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:x='urn:schemas-microsoft-com:office:excel' xmlns='http://www.w3.org/TR/REC-html40'>";
excelFile = "<head>";
excelFile = "<meta http-equiv='content-type' content='application/vnd.ms-excel; charset=UTF-8'>";
excelFile = "<!--[if gte mso 9]>";
excelFile = "<xml>";
excelFile = "<x:ExcelWorkbook>";
excelFile = "<x:ExcelWorksheets>";
excelFile = "<x:ExcelWorksheet>";
excelFile = "<x:Name>";
var worksheet = 'mySheet';
excelFile = worksheet;
excelFile = "</x:Name>";
excelFile = "<x:WorksheetOptions>";
excelFile = "<x:DisplayGridlines/>";
excelFile = "</x:WorksheetOptions>";
excelFile = "</x:ExcelWorksheet>";
excelFile = "</x:ExcelWorksheets>";
excelFile = "</x:ExcelWorkbook>";
excelFile = "</xml>";
excelFile = "<![endif]-->";
excelFile = "</head>";
excelFile = "<body>";
excelFile = excel;
excelFile = "</body>";
excelFile = "</html>";
var uri = 'data:application/vnd.ms-excel;charset=utf-8 ' encodeURIComponent(excelFile);
var link = document.createElement("a");
link.href = uri;
link.style = "visibility:hidden";
link.download = FileName ".xls";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
function exportExcel(){
var JSON_Data = {
data:[
{id:1 name:"王唯" sex:true age:18}
{id:2 name:"JingJing" sex:true age:19}
{id:3 name:"Juanzi" sex:true age:20}
{id:4 name:"Jianguo" sex:true age:21}
]
// title: {id:'ID' name:'姓名' sex:'性别' age:'年龄'}
title: {id:'ID' name:'姓名' age:'年龄'}
};
JSONToExcelConvertor(JSON_Data.data "myexcel");
// 使用标题
// JSONToExcelConvertor(JSON_Data.data "myexcel" JSON_Data.title);
}
</script>
<button onclick="exportExcel();">导出为Excel</button>
第三方插件和库:
插件JsonExportExcel.js:
地址:https://github.com/cuikangjie/JsonExportExcel
<script>
function exportExcel() {
var option={};
option.fileName = 'myexcel' // 下载文件名(默认:download)
// datas数据,多个sheet,每个sheet为一个object
option.datas=[
{
sheetData:[{name:'王唯' sex:true age:18} {name:'JingJing' sex:false age:'19'}] // 数据
sheetName:'sheet' // sheet名称
sheetFilter:['name' 'sex'] //列过滤 用于过滤json中的数据
sheetHeader:['姓名' '性别'] //第一行的标题
}
{
sheetData:[{name:'零点网络' url:'https://www.zeronetwork.cn'} {name:'bing' url:'https://cn.bing.com'}]
sheetName: 'company'
}
];
var toExcel=new ExportJsonExcel(option);
toExcel.saveExcel();
};
</script>
<button onclick="exportExcel();">导出为Excel</button>
XLSX库:
各种电子表格格式的解析器和编写器,可以导出为各种数据格式的文件,地址:https://sheetjs.com/ 或https://github.com/SheetJS/sheetjs;
XLSX包含了很多的模块,完整的版本是dist/xlsx.full.min.js;
引用:
<script src="https://cdn.bootcdn.net/ajax/libs/xlsx/0.17.0/xlsx.full.min.js"></script>
示例:把表格的内容导出到Excel文件中,如:
<script src="https://cdn.bootcdn.net/ajax/libs/xlsx/0.17.0/xlsx.full.min.js"></script>
<table id="data-table" border="1" width="50%">
<tr>
<td>编号</td><td>姓名</td><td>年龄</td><td>出生日期</td>
</tr>
<tr>
<td>1</td><td>王唯</td><td>18</td><td>2001-12-12</td>
</tr>
<tr>
<td>2</td><td>JingJing</td><td>19</td><td>2000-12-12</td>
</tr>
<tr>
<td>3</td><td>Juanzi</td><td>20</td><td>2009-10-10</td>
</tr>
</table>
<table id="course-table" border="1" width="50%">
<tr><td>标题</td> <td>课时</td> <td>主讲</td></tr>
<tr><td>HTML</td> <td>10</td> <td>王唯</td></tr>
<tr><td>CSS</td> <td>20</td> <td>大师哥</td></tr>
<tr><td>JavaScript</td> <td>30</td> <td>零点程序员</td></tr>
</table>
<p><button onclick="exportExcel()">导出Excel</button></p>
<p><button onclick="exportSheets()">导出多个Sheet</button></p>
<script>
function exportExcel(){
var table = document.getElementById('data-table');
// 创建Excel工作簿,即一个Excel文件
var workbook = XLSX.utils.table_to_book(table {
sheet: "SheetJs" // 工作表名称
});
// 导出工作表
return XLSX.writeFile(workbook 'ExportExcel.xlsx');
}
// 导出多个sheet的Excel文件
function exportSheets(){
var table1 = document.getElementById('data-table');
var table2 = document.getElementById('course-table');
// 创建workbook,即工作簿
var workbook = XLSX.utils.book_new();
// 把表格转换为sheet工作表
var sheet1 = XLSX.utils.table_to_sheet(table1);
var sheet2 = XLSX.utils.table_to_sheet(table2);
// 把sheet工作表添加到workbook中
XLSX.utils.book_append_sheet(workbook sheet1 '人员');
XLSX.utils.book_append_sheet(workbook sheet2 '课程');
// 导出Excel
return XLSX.writeFile(workbook 'ExportSheets.xlsx');
}
</script>
可以把JSON数据导出为Excel文件,如:
function exportExcel(){
var persons = [
{name: "王唯" sex: "男" age: 18 createtime: new Date()}
{name: "静静" sex: "女" age: 19 createtime: new Date()}
{name: "娟子" sex: "女" age: 20 createtime: new Date()}
];
var sheet = XLSX.utils.json_to_sheet(persons);
XLSX.utils.book_append_sheet(workbook sheet '人员');
return XLSX.writeFile(workbook 'ExportJson.xlsx');
}
可以基于Excel的工作表sheet生成一个对象数组,如:
function exportExcel(){
var url = "files/one.xls";
var xhr = new XMLHttpRequest();
xhr.open("GET" url true);
xhr.responseType = "arraybuffer";
xhr.onload = function(event){
var data = new Uint8Array(xhr.response);
var workbook = XLSX.read(data {type: "array"});
var sheet = workbook.Sheets[workbook.SheetNames[0]];
console.log(sheet);
var json = XLSX.utils.sheet_to_json(sheet);
console.log(json);
var jsonText = JSON.stringify(json);
console.log(jsonText);
};
xhr.send(null);
}
TableExport:
该插件可以将HTML表格导出到xlsx、xls、csv和txt文件;地址:https://github.com/clarketm/TableExport;但是它需要依赖xlsx及FileSaver.js库;
var table = document.getElementsByTagName("table")[0];
var tableExport = new TableExport(table);
console.log(tableExport);
可以传入其他属性以自定义表、按钮和导出数据的外观,如:
var tableExport = TableExport(document.getElementsByTagName("table")[0] {
headers: true // (Boolean) 是否显示表头,即<thead> 默认为true
footers: true // (Boolean) 是否显示表注 即<tfoot>,默认为false
formats: ["xlsx" "csv" "txt"] // (String[]) 导出的文件格式 默认为['xlsx' 'csv' 'txt']
filename: "id" // (id String) 导出的文件名称,默认为id'
bootstrap: false // (Boolean) 按钮是否使用bootstrap样式 默认为true
exportButtons: true // (Boolean) 是否自动为每个指定格式生成内置的导出按钮,默认为true
position: "bottom" // (top bottom) 标题的位置 默认为'bottom'
ignoreRows: null // (Number Number[]) 要从导出文件中排除的行索引,默认为null
ignoreCols: null // (Number Number[]) 要从导出的文件中排除的列索引,默认为null
trimWhitespace: true // (Boolean) 从单元格文本中删除所有前导/尾随换行符、空格和制表符,默认为false
RTL: false // (Boolean) 将工作表的方向设置为从右向左,默认为false
sheetname: "id" // (id String) 工作表名称,默认为'id'
});
JSON文件的注释:
JSON文件是不能有注释的,根据JSON规范(http://www.json.org RFC 4627 RFC 7159),不支持注释;JSON规范之所以不允许加注释,主要是防止过多的注释,会影响文件本身的数据;
但是有些场合,尤其是配置文件,还是希望能够有帮助说明数据项的含义;一方面有利于描述接口,另一方面能够减少重复性的文档,这在开发过程中有一定的意义;
注释的方法:
1、使用约定的key作为注释字段:
如以"//"、"_comment"、"#####"("#"个数自定) 作为注释的key;但不符合规范,可以几乎所有的JavaScript环境都允许;
2、使用重名key作为注释:
即每个key,使用两次,第1次做注释,第2次做实际属性,解析之后,只保留最后一项;也不符合规范,但几乎所有的JavaScript环境也都允许
3、使用字段key加前缀做注释key:
常用的前缀有”?”、"#"、"_"、"__"等;优点是没有重名的字段,完全符合JSON协议;
4、使用JSON5规范:
JSON5规范允许在JSON文件中加入注释:单行注释,多行注释均可;其用法与内置的JSON对象类似;地址:https://json5.org/;
5、直接用json-schema:
使用规范中的注释字段,地址:http://json-schema.org/优点是功能强大,缺点是json-schema与json数据本身需要分离;
6、使用去注释的库:
可以使用strip-json-comments库,它支持去掉行注释与块注释,然后再可以用标准的JSON.parse解析;地址:https://github.com/sindresorhus/strip-json-comment;
7、使用支持注释的配置文件管理模块:
如rc库,地址:https://github.com/dominictarr/rc,或者config库,地址: https://github.com/lorenwest/node-config;缺点是只能用于配置相关的Json文件;
JSON工具和编辑器:
1.JSON格式化和验证器:
一个在线工具,可以对JSON进行格式化和美化,以便更易于阅读和调试;地址:https://jsonformatter.curiousconcept.com/
2.Altova XMLSpy JSON和 XML编辑器:
是一款JSON和XML编辑工具,提供了用于编辑、建模、转换和调试XML相关技术的各种工具;主要的工具包括图形化模式设计器、代码生成工具、文件转换器、调试器以及用于处理XSLT、XSD、XBRL和SOAP的分析器;其利用RaptorXML Server进行JSON验证和处理;地址:https://www.altova.com/xmlspy-xml-editor/download;
3.Code Beautify JSON工具
Code Beautify JSON工具包括JSON查看器、JSON编辑器、JSON验证器以及JSON到HTML、JSON到XML和JSON到YAML等转换器;
还提供了Excel到JSON转换器和JSON 缩小器;Code Beautify还为XML、HTML、CSV、CSS、RSS、SQL、Base64及其他数据格式和文件类型提供了在线脚本编辑器、美化器、缩小器和转换器;地址:https://codebeautify.org/;
4.Visual Studio Code等IDE:
vsCode内置了支持编辑JSON文件的功能;这包括通过IntelliSense针对属性和值进行验证、快速导航、代码折叠和建议;将鼠标悬停在JSON编辑窗口的左上角,会显示当前JSON的数据结构等;