2012-08-27 16 views
2

我有一個節點數組。 每個節點都有一個子數組和一個指向其父節點的指針。 我想序列化它使用JSON.stringify,但與父指針我顯然最終與循環引用,和JSON引發異常。我能做些什麼來解決循環引用和使用JSON序列化?用JSON序列化圖論樹的解決方法?

相關問題:Chrome sendrequest error: TypeError: Converting circular structure to JSON

+0

我的想法如何處理這一點 - 但給我一些時間... – TheHe

回答

1

你應該有家長的對象來創建自定義的toJSON功能。

documentation

如果被字符串化的對象有一個名爲的toJSON其值 是功能屬性,則的toJSON方法定製JSON字符串化 行爲

var x = { 
    foo: 'foo', 
    toJSON: function() { 
    return 'bar'; 
    } 
}; 
var json = JSON.stringify({x: x}); 

所以你可以在具有父引用的對象中創建該函數,可能是這樣的?

MyObj = function(){ 
    this.xxx = 'foobar'; 
    this.zzz = 'foooobar'; 
    this.name = 'foo'; 
    this.parent = ...; 
    toJSON = function(){ 
     tmp = '{' 
     for(prop in MyObj){ 
      if(prop == 'parent'){ 
       tmp += 'parent: "'+ this['parent'].name +'"'; //maybe?? optional! 
      }else{ 
       tmp += prop + ':' + this[prop].stringify + ','; //you will still use the browser function 
      } 
      tmp += '}    
     } 
     return tmp; 
    } 
} 
+0

你還必須寫一個解析函數,或者是照顧的自動? – Joe

+0

解析時你永遠不會遇到循環引用的問題,所以你可以使用預先構建的函數甚至eval函數,它應該沒問題 –

1

有一個嘗試 - 利用信息和演示數據是在BUTTOM:

// class 
var Decircularizer = function() {}; 
// class contents 
Decircularizer.prototype = { 
    curId: 0x01, 
    idField: '{`id´}', 
    _getNewId: function() { 
     return this.curId++; 
    }, 
    _getVisited: function(obj) { 
     return obj[''+this.idField]; 
    }, 
    _setVisited: function(obj) { 
     return (obj[''+this.idField] = this._getNewId()); 
    }, 
    _removeVisited: function(obj){ 
     delete obj['' + this.idField]; 
    }, 
    decycle: function(obj, depth) { 
     var $this = this; 
     depth = depth || 0; 
     var key = this._getVisited(obj); 
     if (key > 0x00) return this.idField + key; 

     if(!jQuery.isPlainObject(obj)) 
      return obj; 

     key = this._setVisited(obj); 
     jQuery.each(obj, function(prop, val){ 
      if (prop == $this.idField) return; 
      if (jQuery.isFunction(obj[prop])) delete obj[prop]; 
      else obj[prop] = $this.decycle(val, depth + 1); 
     }); 
     return obj; 
    }, 
    recycle: function(obj){ 
     var $this = this; 
     var ids = {}; 
     this._searchIds(obj, ids); 
     return this._recycle(obj, ids); 
    }, 
    _recycle: function(obj, ids){ 
     var $this = this; 
     if(!jQuery.isPlainObject(obj)) 
      return obj; 
     jQuery.each(obj, function(prop, val){ 
      var xval = ids[val]; 
      if(xval) 
       obj[prop] = xval; 
      else 
       obj[prop] = $this._recycle(val, ids); 
     }); 
     return obj; 
    }, 
    _searchIds: function(obj, ids){ 
     var $this = this 
     var ids = ids || {}; 
     var key = this._getVisited(obj); 

     if(key > 0x00) { 
      ids[this.idField + key] = obj; 
      $this._removeVisited(obj); 
     } 

     if(!jQuery.isPlainObject(obj)) 
      return ids; 

     jQuery.each(obj, function(prop, val){ 
      $this._searchIds(val, ids); 
     }); 
     return ids; 
    } 
}; 

// EXAMPLE DATA 
var a = {}; 
var a2 = {} 
a.b = a; 
a.c = "hallo"; 
a.e = 123; 
a.f = a2; 
a2.x = a; 

// USAGE 
// new class 
var ser = new Decircularizer(); 

// uncycle 
var cleanObjectWithOutCirculars = ser.decycle(a); 
console.debug(cleanObjectWithOutCirculars); 


/* object looks like 
Object {c: "hallo", e: 123, b: "{`id´}1", {`id´}: 1, f: Object} 
    b: "{`id´}1" 
    c: "hallo" 
    e: 123 
    f: Object 
     x: "{`id´}1" 
     {`id´}: 2 
     __proto__: Object 
    {`id´}: 1 
    __proto__: Object 
*/ 

// recycle 
var aNew = ser.recycle(cleanObjectWithOutCirculars); 
console.debug(aNew) 

/* 
Object {c: "hallo", e: 123, b: Object, f: Object} 
    b: Object 
     b: Object 
     c: "hallo" 
     e: 123 
    f: Object 
     x: Object 
     __proto__: Object 
    __proto__: Object 
    c: "hallo" 
    e: 123 
    f: Object 
     x: Object 
      b: Object 
      c: "hallo" 
      e: 123 
      f: Object 
      __proto__: Object 
     __proto__: Object 
    __proto__: Object 
*/ 

// correct (Y) 
相關問題