2

ノードの配列があります。各ノードには、子の配列とその親へのポインターがあります。JSON.stringifyを使用してシリアル化したいのですが、親ポインターを使用すると、明らかに循環参照になり、JSONは例外をスローします。循環参照を回避し、JSONでシリアル化するにはどうすればよいですか?

関連する質問:Chrome sendrequestエラー:TypeError:循環構造をJSONに変換しています

4

2 に答える 2

1

試してみてください--usage-informationとdemo-dataは最下位にあります:

// 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)
于 2012-08-28T02:42:10.660 に答える
1

親を持つオブジェクトにカスタマイズされたtoJson関数を作成する必要があります。

ドキュメントから

文字列化されるオブジェクトに、値が関数である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;
    }
}
于 2012-08-28T03:11:47.007 に答える