从 ECMAScript 5th Edition 开始,JavaScript 内建了 JSON 对象,用来处理 JSON 的序列化和反序列化,有以下几个方法原型
JSON.stringify(obj [,filter] [,indent])
JSON.parse(text [,reviver])
jQuery 也提供了 jQuery.parseJSON 方法,但是没有相应的序列化方法。
如果用 JSON.stringify() 来对一个有循环引用的 JSON 对象进行序列化,会产生 TypeError: cyclic object value 异常,类似下面的代码
1 2 3 4 5 6 7 |
var a = {} a.b = a; try{ JSON.stringify(a) }catch(e){ document.write(e); } |
点击链接 http://jsfiddle.net/Unmi/6eLFF/ 运行上面的代码
在 Chrome/Opera 下异常描述是 TypeError: Converting circular structure to JSON
Safari 是这么说的 TypeError: JSON.stringify cannot serialize cyclic structures.
总之就是不能正确序列化 JSON, 于是我们要启用 JSON.stringify() 方法的第二个参数 filter 来巡视中间处理的每一个 JSON 对象是否曾经出现过,再次出现的标记起来,到此为止,不继续往下拆解。
大致的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
obj = { x: 555, y: "hi" } obj.myself = obj var jsonify = function(obj){ var seen = []; var json = JSON.stringify(obj, function(key, value){ if (typeof value === 'object') { if ( !seen.indexOf(value) ) { return '__cycle__' + (typeof value) + '[' + key + ']'; } seen.push(value); } return value; }, 4); return json; }; alert(jsonify(obj)); |
点击链接 http://jsfiddle.net/Unmi/A96tA/ 运行上面的代码
上面判断了了值类型是否是 object 或 [object Object],并且在 seen 数组中已存在的话则就此打住。
对于 JSON.stringify() 产生的循环引用异常,可能有人会想到 for(property in object) 的方式来枚举属性,但这要自己来处理递归,并且是个数组的话就有些怪异。
听说 PhantomJS 来优雅的处理有循环引用的 JSON 序列化部题,PhantomJS 为何物,我未曾深究,它离我们的 Web 浏览器编程的话题好象有点儿远了。
本文链接 https://yanbin.blog/json-stringifyobj-raise-typeerror/, 来自 隔叶黄莺 Yanbin Blog
[版权声明] 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。
[…] Unmi 从 ECMAScript 5th Edition 开始,JavaScript 内建了 JSON 对象,用来处理 JSON […]