Voici un exemple de structure de données avec des références cycliques:
function makeToolshed(){
var nut = {name: 'nut'}, bolt = {name: 'bolt'};
nut.needs = bolt; bolt.needs = nut;
return { nut: nut, bolt: bolt };
}
Lorsque vous souhaitez GARDER les références cycliques (les restaurer lorsque vous les désérialisez, au lieu de les "nuking"), vous avez 2 choix, que je vais comparer ici. Le premier est cycle.js de Douglas Crockford , le second est mon paquet siberia . Les deux fonctionnent en «décyclant» d'abord l'objet, c'est-à-dire en construisant un autre objet (sans aucune référence cyclique) «contenant les mêmes informations».
M. Crockford commence par:
JSON.decycle(makeToolshed())
Comme vous le voyez, la structure imbriquée de JSON est conservée, mais il y a une nouvelle chose, qui est des objets avec la $ref
propriété spéciale . Voyons comment cela fonctionne.
root = makeToolshed();
[root.bolt === root.nut.needs, root.nut.needs.needs === root.nut]; // retutrns [true,true]
Le signe dollar représente la racine. .bolt
avoir $ref
nous dit que .bolt
c'est un objet "déjà vu", et la valeur de cette propriété spéciale (ici, la chaîne $ ["nut"] ["needs"]) nous indique où, voir d'abord ===
ci-dessus. De même pour le deuxième $ref
et le deuxième ===
ci-dessus.
Utilisons un test d'égalité profonde approprié (à savoir la deepGraphEqual
fonction d' Anders Kaseorg issue de la réponse acceptée à cette question ) pour voir si le clonage fonctionne.
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
Maintenant, la Sibérie:
JSON.Siberia.forestify(makeToolshed())
Siberia n'essaye pas d'imiter le JSON "classique", pas de structure imbriquée. Le graphe d'objets est décrit de manière "plate". Chaque nœud du graphe d'objet est transformé en un arbre plat (liste de paires clé / valeur simple avec des valeurs entières uniquement), qui est une entrée dans .forest.
À l'index zéro, nous trouvons l'objet racine, à des indices plus élevés, nous trouvons les autres nœuds de le graphe d'objet et les valeurs négatives (d'une clé d'un arbre de la forêt) pointent vers le atoms
tableau, (qui est tapé via le tableau des types, mais nous ignorerons les détails de saisie ici). Tous les nœuds terminaux sont dans la table des atomes, tous les nœuds non terminaux sont dans la table de la forêt, et vous pouvez voir immédiatement le nombre de nœuds du graphe d'objets, à savoir forest.length
. Testons si cela fonctionne:
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
Comparaison
ajoutera une section plus tard.