我有一个包含循环引用的JavaScript对象定义:它具有一个引用父对象的属性。
它还具有一些我不想传递给服务器的功能。我将如何序列化和反序列化这些对象?
我读过,做到这一点的最好方法是使用道格拉斯·克罗克福德的stringify。但是,我在Chrome中遇到以下错误:
TypeError:将圆形结构转换为JSON
编码:
function finger(xid, xparent){ this.id = xid; this.xparent; //other attributes } function arm(xid, xparent){ this.id = xid; this.parent = xparent; this.fingers = []; //other attributes this.moveArm = function() { //moveArm function details - not included in this testcase alert("moveArm Executed"); } } function person(xid, xparent, xname){ this.id = xid; this.parent = xparent; this.name = xname this.arms = [] this.createArms = function () { this.arms[this.arms.length] = new arm(this.id, this); } } function group(xid, xparent){ this.id = xid; this.parent = xparent; this.people = []; that = this; this.createPerson = function () { this.people[this.people.length] = new person(this.people.length, this, "someName"); //other commands } this.saveGroup = function () { alert(JSON.stringify(that.people)); } }
这是我为这个问题创建的测试用例。这段代码中有错误,但是本质上我在对象中有对象,并且传递给每个对象以显示创建对象时父对象是什么的引用。每个对象还包含一些函数,我不想对其进行字符串化。我只想要的属性Person.Name。
Person.Name
假设传递回相同的JSON,如何在发送到服务器之前进行序列化和反序列化?
*当您拥有对象的属性时,如果对象本身是直接(a -> a)或间接(a -> b -> a)的属性,则会发生 *圆形结构 错误。
a -> a
a -> b -> a
为避免错误消息,请告诉JSON.stringify遇到循环引用时该怎么做。例如,如果您有一个人指向另一个人(“父母”),它可能(也可能不)指向原始人,请执行以下操作:
JSON.stringify( that.person, function( key, value) { if( key == 'parent') { return value.id;} else {return value;} })
to的第二个参数stringify是 过滤器函数 。在这里,它只是将引用的对象转换为其ID,但是您可以随意做任何破坏循环引用的操作。
stringify
您可以使用以下代码测试以上代码:
function Person( params) { this.id = params['id']; this.name = params['name']; this.father = null; this.fingers = []; // etc. } var me = new Person({ id: 1, name: 'Luke'}); var him = new Person( { id:2, name: 'Darth Vader'}); me.father = him; JSON.stringify(me); // so far so good him.father = me; // time travel assumed :-) JSON.stringify(me); // "TypeError: Converting circular structure to JSON" // But this should do the job: JSON.stringify(me, function( key, value) { if(key == 'father') { return value.id; } else { return value; }; });
顺便说一句,我会为“ parent” 选择一个不同的属性名称,因为它是许多语言(和DOM)中的保留字。这往往会引起混乱。
parent