JSON.stringify(obj) 时 TypeError: cyclic object value 异常

从 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 异常,类似下面的代码
1var a = {}
2a.b = a;
3try{
4    JSON.stringify(a)
5}catch(e){
6    document.write(e);
7}
点击链接 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 对象是否曾经出现过,再次出现的标记起来,到此为止,不继续往下拆解。

大致的代码如下:
 1obj = {
 2    x: 555,
 3    y: "hi"
 4}
 5obj.myself = obj
 6
 7var jsonify = function(obj){
 8    var seen = [];
 9    var json = JSON.stringify(obj, function(key, value){
10        if (typeof value === 'object') {
11            if ( !seen.indexOf(value) ) {
12                return '__cycle__' + (typeof value) + '[' + key + ']';
13            }
14            seen.push(value);
15        }
16        return value;
17    }, 4);
18    return json;
19};
20
21alert(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's Blog
[版权声明] 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。