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 $ref
Eigenschaft. 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. .bolt
Nachdem $ref
wir erfahren haben, dass .bolt
es 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 $ref
und die zweite ===
oben.
Verwenden wir einen geeigneten Tiefengleichheitstest (nämlich Anders Kaseorgs deepGraphEqual
Funktion 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 atoms
Array (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.