JavaScript JSON
JSON 对象包含两个 方法 : 用于解析 JavaScript Object Notation (JSON) 的 parse() 方法 ,以及将对象/值转换为 JSON字符串的 stringify() 方法 。除了这两个 方法 , JSON 这个对象本身并没有其他作用,也不能被 调用 或者作为构造 函数 调用 。
JavaScript 内置的 JSON对象 用于处理 JSON 。
JSON(JavaScript Object Notation)是一种带有格式的文本,JavaScript 中的 JSON对象 用于处理这种文本。
JSON 对象只提供了两个 方法 , 一个 用于序列化 JSON , 一个 用于反序列化 JSON 。
这里的序列化可以理解成 将JavaScirpt对象转换成JSON ,反序列化则是 将JSON转换成JavaScript对象 。
1. JSON.parse
JSON.parse 用于解析 JSON 格式的字符串,将 JSON 转化成 JavaScript 对象。
JSON . parse ( JSON字符串 , 处理 函数 ) ;
第 一个 参数是要转换成对象的 JSON 字符串,第二个参数可以不传递/
var str = '{ "name": "baba", "age": 12, "info": { "locate": "浙江" } }' ; var user = JSON . parse ( str ) ; console . log ( user ) ; // 输出 一个 JavaScript 对象
传递给 JSON.parse 方法 的字符串要符合 JSON 标准,否则会报错。
第二个参数非常有趣,传入的是 一个 函数 ,这个 函数 会在每个 JSON 属性 被解析的时候 调用 ,同时会传递 属性 名和 属性 值给 函数 作为参数,传入参数的返回值会作为当前遍历到的 属性 的新值。
var str = '{ "name": "baba", "age": 12, "info": { "locate": "浙江" } }' ; var user = JSON . parse ( str , function ( key , value ) { console . log ( key , value ) ; return value ; } ) ;
可以发现上述例子打印的最后以想, 属性 名是可以空字符串, 属性 值是解析完的结果。
修改 一下例子,将返回值改成 一个 固定的值。
var str = '{ "name": "baba", "age": 12, "info": { "locate": "浙江" } }' ; var user = JSON . parse ( str , function ( key , value ) { console . log ( key , value ) ; return '强行 修改 值' ; } ) ;
观察 输出 后,可以发现所有 属性 都被遍历了,并且赋值成功,但是最终 user 也变成了返回的字符串。
这是因为当解析完成后,传入的 函数 会被最后 调用 一次,传递进来的值就是最终 JSON.parse 的返回值,所以对其 修改 后,会影响到的最终结果。
var str = '{ "name": "baba", "age": 12, "info": { "locate": "浙江" } }' ; var user = JSON . parse ( str , function ( key , value ) { console . log ( key , value ) ; if ( key === '' ) { return value ; } return '强行 修改 值' ; } ) ;
对传递过来的 属性 名为空字符串 '' 进行单独处理即可避免这种特殊情况。
业务逻辑中很少会用第二个参数来处理解析 内容 。
2. JSON.stringify
JSON.stringify 用于将JavaScript对象转换成 JSON 格式的字符串。
JSON . stringify ( JavaScript对象 , 处理 函数 , 缩进空格字符 数量 ) ;
第 一个 参数是需要转换成 JSON 字符串的对象。
第二个参数可以是个 函数 ,也可以是个数组。
如果是 函数 ,则每 一个 属性 在处理的时候就被 调用 这个 函数 ,同时 属性 名和 属性 值作为参数传递给这个 函数 ,并且 函数 的返回值作为这个处理 属性 的值。
如果是数组,则只有 属性 名在数组中的 属性 才会被处理,不传递则 默 认处理整个对象。
如果第二个参数传递 null ,也就是不做特殊处理,在使用到第三个参数的时候,第二个参数会传递 null 。
第三个参数可以传递数字,也可以传递字符串,传递了这个参数会对结果做格式化,具有一定的格式,参数的值决定格式化的样式。
如果是数字,则使用对应长度的空格来缩进,长度 1 到 10 ,比 1 小则表示不缩进。
如果是字符串,则会使用传入的字符串进行缩进,传入的字符串长度超过 10 ,则会 截取 前 10 个作为缩进字符。
var user = { name : '小明' , age : , skill : [ 'HTML' , 'Java' ] , } ; var json = JSON . stringify ( user ) ; console . log ( json ) ; // 输出 :{"name":"小明","age":14,"skill":["HTML","Java"]}
第二个参数用起来和 parse 方法 的第二个参数类似。
var user = { name : '小明' , age : , skill : [ 'HTML' , 'Java' ] , } ; var json = JSON . stringify ( user , function ( key , value ) { console . log ( key , vlue ) ; return value ; } ) ; console . log ( json ) ;
根据上述例子可以看到,先 输出 的 属性 为空字符串, 属性 值为被处理对象,所以如果不想操作原对象,需 要做 特殊处理。
var user = { name : '小明' , age : , skill : [ 'HTML' , 'Java' ] , } ; var json = JSON . stringify ( user , function ( key , value ) { if ( key === '' ) { return value ; } return '我是处理过的值' ; } ) ; console . log ( json ) ;
这样处理后,最终处理完的 JSON 字符串的 属性 值都是 函数 的返回值了。
第三个参数会在做一些工具类调试的时候常用到。
var obj = [ { path : '/' , component : 'function() {}' , children : [ { path : 'note' , component : 'function() {}' , } , { path : 'friends' , component : 'function() {}' , } ] } , { path : '*' , component : 'function() {}' , } ] ; var json1 = JSON . stringify ( obj , null ) ; var json2 = JSON . stringify ( obj , null , ) ; var json3 = JSON . stringify ( obj , null , '*-*' ) ; console . log ( json1 ) ; // 没有格式 console . log ( json2 ) ; // 使用两个空格控制的缩进 console . log ( json3 ) ; // 使用 *-* 控制的缩进
传入参数后就会将处理后的 JSON 字符串进行格式化,缩进部分根据传入的参数值决定。
3. 其他注意点
3.1 深拷贝
可以配合 JSON 的两个 方法 ,对对象进行深拷贝。
var obj = { prop : 'value' } ; var newObj = JSON . parse ( JSON . stringify ( obj ) ) ; newObj . prop = 'new value' ; console . log ( obj ) ; console . log ( newObj ) ;
根据结果可以看到新的对象 修改 ,没有影响到原对象,两者之间不存在引用关系。
3.2 序列化规则
使用 JSON.stringify 有些内置规则。
如果对象中存在包装对象,则在转换过程中会变成原始值。
var obj = { string : new String ( 'A promise is a promise.' ) , number : new Number ( ) , } ; var result = JSON . stringify ( obj ) ; console . log ( result ) ; // 输出 :"{"string":"A promise is a promise.","number":996}"如果转换的对象或者对象下的 属性 存在 toJSON 方法 ,那么这个 方法 的返回值会作为转换结果。
var user = { nickname : 'joker' , toJSON : function ( ) { return 'hahahahahahaha' ; } , } var result = JSON . stringify ( user ) ; console . log ( result ) ; // 输出 :"hahahahahahaha"
可以看到结果为 toJSON 方法 的返回值。
除了数组以外的对象,转换结果顺序为 随机 。
var obj = { b : , c : , a : , } ;
如以上对象,转换的结果有可能是以下情况中的一种:
"{" a ":1," b ":2," c ":3}" "{" a ":1," c ":3," b ":2}" "{" b ":2," a ":1," c ":3}" "{" b ":2," c ":3," a ":1}" "{" c ":3," b ":2," a ":1}" "{" c ":3," a ":1," b ":2}"undefined、ES6 中的 symbol 值、 函数 在转换过程中都会被忽略,当然 函数 如果具有 toJSON 方法 依然会优先选择 toJSON 方法 的结果。
var fn = function ( ) { } ; fn . toJSON = function ( ) { return '我是 函数 ' } ; var result = JSON . stringify ( { a : fn , b : Symbol ( ) , c : undefined , d : function ( ) { } , } ) ; console . log ( result ) ;存在循环引用,则会报错
var obj1 = { prop1 : , } ; var obj2 = { prop1 : , } ; obj1 . prop2 = obj2 ; obj2 . prop2 = obj1 ; JSON . stringify ( obj1 ) ; // TypeError: Converting cir cula r structure to JSON
两个对象相互引用之后,进行系列化就会抛出 错误 。
在 ES6 中,symbol 可以作为对象的 属性 值,但在处理的时候都会被忽略。
var symbol = Symbol ( ) ; var obj = { prop1 : 'value1' , [ symbol ] : 'value2' , } ; console . log ( obj ) ; var result = JSON . stringify ( obj ) ; console . log ( result ) ; // 输出 :{"prop1":"value1"}null、正负 Infinity、NaN 在序列化时都会被当作 null 。
var obj = { null : null , infinity1 : + , infinity2 : - , : , } ; var result = JSON . stringify ( obj ) ; console . log ( result ) ; // 输出 :{"null":null,"infinity1":null,"infinity2":null,"NaN":null}
4. 小结
JSON 几乎是目前前后端交互最常用的数据格式,所以 JSON 对象使用的频率也很高。
在使用 JSON.parse 反序列化的时候,如果 JSON 格式不符合规范,是会报错的,日常开发中建议封装一层 JSON 的 方法 ,将 错误 集中处理,方便定位与上报 错误 。
什么是 DOM ? ?JavaScript RegExp声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://www.haodehen.cn/did92417