Ecco un esempio di una struttura di dati con riferimenti ciclici:
function makeToolshed(){
var nut = {name: 'nut'}, bolt = {name: 'bolt'};
nut.needs = bolt; bolt.needs = nut;
return { nut: nut, bolt: bolt };
}
Quando desideri MANTENERE i riferimenti ciclici (ripristinali quando li deserializzi, invece di "sfumarli"), hai 2 opzioni, che confronterò qui. Il primo è il ciclo.js di Douglas Crockford , il secondo è il mio pacchetto Siberia . Entrambi funzionano innanzitutto "deciclando" l'oggetto, ovvero costruendo un altro oggetto (senza riferimenti ciclici) "contenente le stesse informazioni".
Il signor Crockford va per primo:
JSON.decycle(makeToolshed())
Come vedi, la struttura nidificata di JSON viene mantenuta, ma c'è una nuova cosa, ovvero gli oggetti con la $ref
proprietà speciale . Vediamo come funziona.
root = makeToolshed();
[root.bolt === root.nut.needs, root.nut.needs.needs === root.nut]; // retutrns [true,true]
Il simbolo del dollaro rappresenta la radice. .bolt
averci $ref
detto che .bolt
è un oggetto "già visto", e il valore di quella proprietà speciale (qui, la stringa $ ["nut"] ["needs"]) ci dice dove, vedi prima ===
sopra. Allo stesso modo per il secondo $ref
e il secondo ===
sopra.
Usiamo un test di uguaglianza profonda adeguato (vale a dire la deepGraphEqual
funzione di Anders Kaseorg dalla risposta accettata a questa domanda ) per vedere se la clonazione funziona.
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
Ora, Siberia:
JSON.Siberia.forestify(makeToolshed())
La Siberia non tenta di imitare JSON "classico", nessuna struttura nidificata. Il grafico dell'oggetto è descritto in modo "piatto". Ogni nodo del grafico degli oggetti viene trasformato in un albero piatto (elenco di coppie di valori di chiave semplice con valori solo interi), che è una voce in .forest.
A indice zero, troviamo l'oggetto radice, a indici più alti, troviamo gli altri nodi di il grafico dell'oggetto e i valori negativi (di una chiave di un albero della foresta) puntano alla atoms
matrice (che viene digitata dalla matrice dei tipi, ma salteremo qui i dettagli di battitura). Tutti i nodi terminali sono nella tabella degli atomi, tutti i nodi non terminali sono nella tabella della foresta e puoi vedere subito quanti nodi ha il grafico a oggetti, vale a dire forest.length
. Testiamo se funziona:
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
confronto
aggiungerà la sezione in seguito.