Hier ist ein Beispiel für eine Datenstruktur mit zyklischen Referenzen:

function makeToolshed(){
var nut = {name: 'nut'}, bolt = {name: 'bolt'};
nut.needs = bolt; bolt.needs = nut;
return { nut: nut, bolt: bolt };
}
Wenn Sie die zyklischen Referenzen BEHALTEN möchten (stellen Sie sie beim Deserialisieren wieder her, anstatt sie zu "nuken"), haben Sie zwei Möglichkeiten, die ich hier vergleichen werde. Erstens ist Douglas Crockfords cycle.js , zweitens ist mein Sibirien- Paket. Beide arbeiten, indem sie zuerst das Objekt "decycling", dh ein anderes Objekt (ohne zyklische Referenzen) konstruieren, "das die gleichen Informationen enthält".
Herr Crockford geht zuerst:
JSON.decycle(makeToolshed())

Wie Sie sehen, bleibt die verschachtelte Struktur von JSON erhalten, aber es gibt eine neue Sache, nämlich Objekte mit der speziellen $refEigenschaft. Mal sehen, wie das funktioniert.
root = makeToolshed();
[root.bolt === root.nut.needs, root.nut.needs.needs === root.nut]; // retutrns [true,true]
Das Dollarzeichen steht für die Wurzel. .boltNachdem $refwir erfahren haben, dass .boltes sich um ein "bereits gesehenes" Objekt handelt, und der Wert dieser speziellen Eigenschaft (hier der String $ ["nut"] ["need"]) sagt uns, wo, siehe zuerst ===oben. Ebenso für die zweite $refund die zweite ===oben.
Verwenden wir einen geeigneten Tiefengleichheitstest (nämlich Anders Kaseorgs deepGraphEqualFunktion aus der akzeptierten Antwort auf diese Frage ), um festzustellen, ob das Klonen funktioniert.
root = makeToolshed();
clone = JSON.retrocycle(JSON.decycle(root));
deepGraphEqual(root, clone) // true
serialized = JSON.stringify(JSON.decycle(root));
clone2 = JSON.retrocycle(JSON.parse(serialized));
deepGraphEqual(root, clone2); // true
Nun, Sibirien:
JSON.Siberia.forestify(makeToolshed())

Sibirien versucht nicht, "klassisches" JSON nachzuahmen, keine verschachtelte Struktur. Der Objektgraph wird "flach" beschrieben. Jeder Knoten des Objektgraphen wird in einen flachen Baum umgewandelt (einfache Schlüsselwertpaarliste mit nur ganzzahligen Werten). Dies ist ein Eintrag in .forest.Bei Index Null finden wir das Stammobjekt, bei höheren Indizes finden wir die anderen Knoten von Das Objektdiagramm und negative Werte (eines Schlüssels eines Baums der Gesamtstruktur) verweisen auf das atomsArray (das über das Array types eingegeben wird, aber die Eingabedetails werden hier übersprungen). Alle Endknoten befinden sich in der Atomtabelle, alle nicht-Endknoten befinden sich in der Gesamtstrukturtabelle, und Sie können sofort sehen, wie viele Knoten der Objektgraph hat, nämlich forest.length. Testen wir, ob es funktioniert:
root = makeToolshed();
clone = JSON.Siberia.unforestify(JSON.Siberia.forestify(root));
deepGraphEqual(root, clone); // true
serialized = JSON.Siberia.stringify(JSON.Siberia.forestify(root));
clone2 = JSON.Siberia.unforestify(JSON.Siberia.unstringify(serialized));
deepGraphEqual(root, clone2); // true
Vergleich
wird später einen Abschnitt hinzufügen.