如何对具有循环指针的循环JSON对象进行编码和解码?
如何对具有循环指针的循环JSON对象进行编码和解码?
我有一个包含循环引用的JavaScript对象定义:它有一个属性引用了父对象。
它还有一些我不想传递给服务器的函数。我应该如何序列化和反序列化这些对象?
我读到最好的方法是使用Douglas Crockford的stringify。然而,在Chrome中我得到以下错误:
TypeError: 将循环结构转换为JSON
代码:
function finger(xid, xparent){ this.id = xid; this.xparent; //其他属性 } function arm(xid, xparent){ this.id = xid; this.parent = xparent; this.fingers = []; //其他属性 this.moveArm = function() { //moveArm函数的详细内容-在这个测试用例中未包含 alert("moveArm已执行"); } } 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"); //其他命令 } this.saveGroup = function () { alert(JSON.stringify(that.people)); } }
这是我为这个问题创建的一个测试用例。这段代码中有错误,但本质上我有对象中的对象,并且在创建对象时传递了对每个对象的父对象的引用。每个对象还包含函数,我不想将其字符串化。我只想要属性,例如Person.Name
。
在发送到服务器之前如何序列化并在传回相同的JSON时如何反序列化?
问题的原因是JSON不能表示包含循环引用的对象,而解决方法是使用Dojo的ref模块来进行字符串化和解析。在这个问题中,提到了使用Dojo的toJson和fromJson方法来处理循环引用的对象。此外,还提到了其他资源和方法,如使用jquery和自定义stringify方法来处理循环引用的对象。
在代码示例中,首先使用Dojo的ref模块将一个包含循环引用的对象进行字符串化,然后使用alert方法显示字符串化后的结果。结果中,循环引用的部分被替换成了"$ref"字段。同时,还提到了使用dojox.json.ref.fromJson方法来将字符串化后的对象进行解析。
在其他资源中,提到了其他方法来处理循环引用的对象,如使用cycle.js库或自定义的方法。同时还提到了JSON.stringify方法和JSON对象的特点。
最后,提到了Dojo的ref模块能够很好地处理循环引用的对象,并解决了问题。
循环结构错误发生在对象的属性直接(a -> a)或间接(a -> b -> a)指向自身的情况下。
为了避免错误信息,可以告诉JSON.stringify在遇到循环引用时应该怎么做。
例如,如果有一个人指向另一个人(“父母”),父母可能(也可能不会)指向原始人,可以采取以下步骤:
JSON.stringify(that.person, function(key, value) { if (key == 'parent') { return value.id; } else { return value; } })
`stringify`的第二个参数是一个过滤函数。在这里,它只是将所引用的对象转换为其ID,但你可以按照自己的需要做任何你想要的操作来打破循环引用。
可以使用以下代码进行测试:
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); // 运行正常 him.father = me; // 假设时间旅行 :-) JSON.stringify(me); // "TypeError: Converting circular structure to JSON" // 但下面的代码可以解决问题: JSON.stringify(me, function(key, value) { if (key == 'father') { return value.id; } else { return value; }; });
顺便说一下,我会选择一个不同的属性名来替换“parent”,因为它是许多语言(以及DOM)中的保留字。这往往会在后续过程中引起混淆...
我们应该用什么来替换变量“parent”?
通常情况下,可以使用“owner”来替代“parent”。
如何对具有循环指针的循环JSON对象进行编码和解码?
在处理循环引用的JSON对象时,通常会遇到编码和解码的问题。编码是将对象转换为JSON字符串的过程,而解码是将JSON字符串转换回原始对象的过程。
上述代码提供了一种不使用库的方法来编码和解码具有循环指针的循环JSON对象。下面将解释代码中使用的方法以及如何使用它们。
首先,我们使用一个叫做"refReplacer"的函数作为JSON.stringify方法的replacer参数。这个函数的作用是将循环引用的对象转换为字符串引用(类似于json-path)。它使用了两个Map对象,分别用于存储对象和路径之间的映射关系。在函数内部,我们通过递归遍历对象的所有属性,并根据属性的类型和值决定如何处理它们。如果属性的值是一个复杂对象(即Object类型),我们将其存储到对象Map中,并将其路径存储到路径Map中。如果属性的值是一个循环引用的对象,我们将其替换为字符串引用(以"#REF:"开头的路径字符串)。最后,我们返回替换后的值。
接下来,我们使用一个叫做"parseRefJSON"的函数来解码包含字符串引用的JSON字符串。这个函数首先创建了两个Map对象,用于存储路径和对象之间的映射关系。然后,它使用JSON.parse方法将JSON字符串转换为原始对象。接着,我们使用递归遍历的方式,将对象和路径之间的映射关系存储到Map对象中。如果存在循环引用的情况,我们将其替换为对应的对象引用。最后,我们返回解码后的对象。
在代码的最后,我们提供了一些测试用例来演示如何使用这两个函数。在测试用例中,我们创建了一个具有循环引用和重复引用的对象,并使用"refReplacer"函数对其进行编码。然后,我们使用"parseRefJSON"函数对编码后的字符串进行解码,并打印出解码后的对象。
通过使用这两个函数,我们可以方便地编码和解码具有循环指针的循环JSON对象。这对于处理复杂的对象结构和数据关系非常有用。