Stringify (convertire in JSON) un object JavaScript con riferimento circolare

Ho una definizione di object JavaScript che contiene un riferimento circolare: ha una proprietà che fa riferimento all’object padre.

Ha anche funzioni che non voglio essere passato al server. Come posso serializzare e deserializzare questi oggetti?

Ho letto che il metodo migliore per farlo è quello di utilizzare le stringify di Douglas Crockford. Tuttavia, sto riscontrando il seguente errore in Chrome:

TypeError: Converting circular structure to JSON 

Il codice:

 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)); } } 

Questo è un test case che ho creato per questa domanda. Ci sono errori all’interno di questo codice, ma essenzialmente ho oggetti all’interno degli oggetti e un riferimento passato a ciascun object per mostrare quale sia l’object genitore quando viene creato l’object. Ogni object contiene anche funzioni, che non voglio essere unificate. Voglio solo le proprietà come Person.Name .

    Come faccio a serializzare prima di inviare al server e deserializzare assumendo che lo stesso JSON sia passato?

    Errore di struttura circolare si verifica quando si ha una proprietà dell’object che è direttamente l’object stesso ( a -> a ) o indirettamente ( a -> b -> a ).

    Per evitare il messaggio di errore, dire a JSON.stringify cosa fare quando incontra un riferimento circolare. Ad esempio, se hai una persona che punta a un’altra persona (“genitore”), che può (o potrebbe non) indicare la persona originale, procedi come segue:

     JSON.stringify( that.person, function( key, value) { if( key == 'parent') { return value.id;} else {return value;} }) 

    Il secondo parametro da stringify è una funzione di filtro . Qui converte semplicemente l’object indicato nel suo ID, ma sei libero di fare ciò che vuoi per rompere il riferimento circolare.

    È ansible testare il codice precedente con il seguente:

     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; }; }); 

    A proposito, sceglierei un nome di attributo diverso da ” parent ” poiché è una parola riservata in molte lingue (e in DOM). Questo tende a causare confusione lungo la strada …

    Sembra che dojo possa rappresentare riferimenti circolari in JSON nella forma: {"id":"1","me":{"$ref":"1"}}

    Ecco un esempio:

    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); });​ 

    produce:

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

    Nota: è anche ansible dojox.json.ref.fromJson questi oggetti di riferimento circolari utilizzando il metodo dojox.json.ref.fromJson .

    Altre risorse:

    Come serializzare il nodo DOM su JSON anche se ci sono riferimenti circolari?

    JSON.stringify non può rappresentare riferimenti circolari

    Ho trovato due moduli adatti per gestire i riferimenti circolari in JSON.

    1. CircularJSON https://github.com/WebReflection/circular-json il cui output può essere utilizzato come input per .parse (). Funziona anche in Browsers & Node.js Vedi anche: http://webreflection.blogspot.com.au/2013/03/solving-cycles-recursions-and-circulars.html
    2. Isaacs json-stringify-safe https://github.com/isaacs/json-stringify-safe che forse è più leggibile ma non può essere usato per .parse ed è disponibile solo per Node.js

    Ognuno di questi dovrebbe soddisfare le tue esigenze.

    Successo su questo thread perché avevo bisogno di registrare oggetti complessi in una pagina, poiché il debug remoto non era ansible nella mia particolare situazione. Trovato cycle.js di Douglas Crockford (inceptor of JSON), che annota i riferimenti circolari come stringhe in modo tale che possano essere ricollegati dopo l’analisi. La copia profonda riciclata è sicura per passare attraverso JSON.stringify. Godere!

    https://github.com/douglascrockford/JSON-js

    cycle.js: questo file contiene due funzioni, JSON.decycle e JSON.retrocycle, che consentono di codificare strutture e dags ciclici in JSON e di ripristinarli. Questa è una funzionalità che non viene fornita da ES5. JSONPath viene utilizzato per rappresentare i collegamenti.

    Ho usato il seguente per eliminare i riferimenti circolari:

     JS.dropClasses = function(o) { for (var p in o) { if (o[p] instanceof jQuery || o[p] instanceof HTMLElement) { o[p] = null; } else if (typeof o[p] == 'object' ) JS.dropClasses(o[p]); } }; JSON.stringify(JS.dropClasses(e));