暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

JSON

Turbo的札记 2020-07-23
298

1.概念

全称JavaScript Object Notiation,JavaScript对象表示法,注意,它不是一种编程语言也不是什么其它,只是一种数据格式!

它是JavaScript地严格子集,利用了JS的一些模式来表示结构化的数据,但不止有JavaScript使用JSON,很多编程语言都有针对JSON的解析器和序列化器。

JSON仅仅是一种在数据传输时表示数据内容的一种方法,后面的全文都讲围绕如何使用这种方法表示数据。

JSON叫全了是JSON字符串,它是以字符串的形式存在的。

2.基础语法

JSON支持下面三种类型的值:

简单值:字符串、数值、布尔值、null,但不支持undefined、NaN、Infinity、-Infinity,使用与JS相同的语法。字符串必须使用双引号(单引号会引起语法错误)。
对象:无序键值对,键值对的值可以是简单值、对象或下面介绍的数组。属性名(key)必须用双引号括起,不声明变量末尾没有分号(详见后),对象内同一层级下属性名不可以重复。
数组:有序值列表(没有键or键即索引),通过索引来访问值,数组的值同对象一样,可以是简单值、对象或数组。同对象一样,也没有变量与分号。

上面提到的这三种值均是以不具名的字面量之间呈现的,即JSON不支持变量;除此之外JSON也不支持函数、对象实例、正则表达式对象、日期对象。

3.使用

本文只介绍JavaScript中如何处理JSON格式数据

ECMAScript5中定义了原生对象JSON,专门用于处理改格式数据IE 8+Firefox 3.5+Safari 4+ChromeOpera 10.5+

但早期并没有这一原生类型,基本上在使用JS的 eval() 函数,由于JSON是JS的语法子集,所以 eval() 函数可以解析、解释并返回JavaScript对象和数组,但使用该函数对JSON数据结构求值存在风险可能会执行一些恶意代码,所以对于旧版本不支持原生JSON对象的浏览器,推荐使用一个shim:https://github.com/douglascrockford/JSON-js。

JSON对象提供两个静态方法:JSON.stringfy() 和 JSON.parse() 。前者用于将符合JSON语法的JS对象序列化为JSON格式的字符串,后者用于这一过程的逆向。

3.1 JSON.stringify()

3.1.1基础用法

用于将一个符合JSON格式的值转为JSON字符串(JSON格式的数据),并且可以被 JSON.parse() 方法还原。这一过程称为序列化。

ps:注意对于原始类型的字符串,转换结果会带双引号:

JSON.stringify(false) // "false"
JSON.stringify('false') // "\"false\""


打印出结果应该为""false"",因为将来还原的时候,内层双引号可以让 JavaScript 引擎知道,这是一个字符串,而不是其他类型的值(本例中若不这样做,false就会被当作布尔类型)。

如果对象中的属性是undefined、函数、XML对象等不合法的数据类型,属性会被JSON.stringify()方法自动忽略过滤掉;若是数组成员中有这样的值,会被转换为null;该方法还会忽略掉不可遍历的属性。

var obj = {};
Object.defineProperties(obj, {
'foo': {
value: 1,
enumerable: true
},
'bar': {
value: 2,
enumerable: false
}
});


JSON.stringify(obj); // "{"foo":1}" 其中bar就是不可遍历,所以被忽略了。


3.1.2 第二个参数

用法一:JSON.stringify() 方法还可以接受一个数组作为第二个参数,指定需要转化为字符串的属性,生成的JSON字符串将只包含数组中列出的属性,实现过滤。只对对象的属性有效。

var obj = {
'prop1': 'value1',
'prop2': 'value2',
'prop3': 'value3'
};


var selectedProperties = ['prop1', 'prop2'];


JSON.stringify(obj, selectedProperties)
// "{"prop1":"value1","prop2":"value2"}"


用法二:第二个参数还可以是函数,用来更改JSON.stringify()的返回值。函数接受两个参数分别是被转换对象化的键名(key)和键值(value)。关于这个函数起到的作用,语言很难表述清:即有点遍历所有键值对儿执行函数体内容的意思,又有点递归的意思。所以还是看下面的示例代码吧。

看这三个示例时需要注意四点:

函数中return的内容;

函数第一次执行的并不是键值对,而是对象本身,无键名;

递归处理中,每一次被执行函数体内容的,都是前一次返回的值;

如果处理函数返回undefined或无返回值,该属性(键值对)会被忽略。

var o = {a: {b: 1}};


function f(key, value) {
console.log("["+ key +"]:" + value);
return value;
}


JSON.stringify(o, f)
// []:[object Object]
// [a]:[object Object]
// [b]:1
// '{"a":{"b":1}}'


var o = {a: 1};


function f(key, value) {
if (typeof value === 'object') {
return {b: 2};
}
return value * 2;
}


JSON.stringify(o, f)
// "{"b": 4}"


function f(key, value) {
if (typeof(value) === "string") {
return undefined;
}
return value;
}


JSON.stringify({ a: "abc", b: 123 }, f)
// '{"b": 123}'


3.1.3 第三个参数:

还可以接受第三个参数用于增加返回的JSON字符串的可读性。

该参数为数字或字符串,如果是数字则表示每个属性前面添加的空格数(最多不超过十个),如果是字符串则之间添加在每行键值对的前面(不超过十个)。第二个参数要用null占位(不可以是空格)。

JSON.stringify({ p1: 1, p2: 2 }, null, 2);
/*
"{
"p1": 1,
"p2": 2
}"
*/


JSON.stringify({ p1:1, p2:2 }, null, '|-');
/*
"{
|-"p1": 1,
|-"p2": 2
}"
*/


3.1.4 toJSON方法

作为JSON.stringify()第一个参数的对象,内部如果有toJSON方法,JSON.stringify()会将toJSON方法的返回值作为第一个参数,而不是对象本身,会忽略原对象的其它属性。

toJSON方法可以自定义的,也可以是通过原生类型继承的,例如Date对象就有自己的toJSON方法:

var date = new Date('2015-01-01');date.toJSON() // "2015-01-01T00:00:00.000Z"JSON.stringify(date) // ""2015-01-01T00:00:00.000Z""
toJSON方法有一个应用:将正则对象转为字符串,这样就可以转换JSON对象了。
var obj = {
reg: /foo/
};


// 不设置 toJSON 方法时
JSON.stringify(obj) // "{"reg":{}}"


// 设置 toJSON 方法时
RegExp.prototype.toJSON = RegExp.prototype.toString;
JSON.stringify(/foo/) // ""/foo/""


3.2 JSON.parse()

该方法用于将JSON字符串转成对应的值(JavaScript对象)。这一过程也称为解析。

注意JSON格式的数据是字符串,所以给该方法传参字面量最外层要带上引号,如果传的是变量则变量应为字符串类型。

如果传入的字符串不是有效的 JSON 格式,JSON.parse()方法将报错。

JSON.parse()可以接受一个处理函数作为第二个参数,用法于上文类似。




参考:

  • Nicholas C.Zakas,JavaScript高级程序设计-JSON

  • 阮一峰,JavaScript教程-JSON

本教程采用知识共享 署名-相同方式共享 3.0协议。

http://creativecommons.org/licenses/by-sa/3.0/

文章转载自Turbo的札记,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论