将具有循环引用的JavaScript对象字符串化(转换为JSON)

我有一个包含循环引用的JavaScript对象定义:它有一个引用父对象的属性。

它还具有我不想传递给服务器的功能。 我将如何序列化和反序列化这些对象?

我读过这样做的最好方法是使用Douglas Crockford的stringify。 但是,我在Chrome中收到以下错误:

TypeError: Converting circular structure to 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这样的属性。

如何在发送到服务器之前序列化并假设传回相同的JSON来对其进行反序列化?


如果直接( 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); // 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)中的保留字。 这往往会导致混乱...


看来,dojo可以用以下形式表示JSON中的循环引用: {"id":"1","me":{"$ref":"1"}}

这里是一个例子:

http://jsfiddle.net/dumeG/

require(["dojox/json/ref"], function(){
    var me = {
        name:"Kris",
        father:{name:"Bill"},
        mother:{name:"Karen"}
    };
    me.father.wife = me.mother;
    var jsonMe = dojox.json.ref.toJson(me); // serialize me
    alert(jsonMe);
});​

生产:

{
   "name":"Kris",
   "father":{
     "name":"Bill",
     "wife":{
          "name":"Karen"
      }
   },
   "mother":{
     "$ref":"#father.wife"
   }
}

注意:您也可以使用dojox.json.ref.fromJson方法对这些循环引用的对象进行反序列化。

其他资源:

即使有循环引用,如何将DOM节点序列化为JSON?

JSON.stringify不能表示循环引用


我找到了两个合适的模块来处理JSON中的循环引用。

  • CircularJSON https://github.com/WebReflection/circular-json,其输出可用作.parse()的输入。 它也适用于Browsers&Node.js另请参阅:http://webreflection.blogspot.com.au/2013/03/solving-cycles-recursions-and-circulars.html
  • Isaacs json-stringify-safe https://github.com/isaacs/json-stringify-safe它可能更具可读性,但不能用于.parse,仅适用于Node.js
  • 这些都应该满足您的需求。

    链接地址: http://www.djcxy.com/p/4793.html

    上一篇: Stringify (convert to JSON) a JavaScript object with circular reference

    下一篇: Mocking a method with throw() specifier