以下は、循環参照のあるデータ構造の例です。
function makeToolshed(){
var nut = {name: 'nut'}, bolt = {name: 'bolt'};
nut.needs = bolt; bolt.needs = nut;
return { nut: nut, bolt: bolt };
}
あなたがしたい場合はKEEP循環参照を(あなたがデシリアライズ時に代わりにそれらを「ニューキング」の、それらを復元)、あなたは私がここで比較します2つの選択肢を持っています。1つ目はDouglas Crockfordのcycle.jsで、2つ目は私のシベリアですパッケージです。どちらも最初にオブジェクトを「デサイクル」することで機能します。つまり、「同じ情報を含む」別のオブジェクト(循環参照なし)を構築します。
クロックフォード氏が最初に行く:
JSON.decycle(makeToolshed())
ご覧のように、JSONの入れ子構造は保持されていますが、特別な$ref
プロパティを持つオブジェクトという新しいものがあります。それがどのように機能するか見てみましょう。
root = makeToolshed();
[root.bolt === root.nut.needs, root.nut.needs.needs === root.nut]; // retutrns [true,true]
ドル記号はルートを表します。.bolt
持っている$ref
ことを教えてくれる.bolt
「すでに見」オブジェクトであり、そして、最初の参照場所は、特別なプロパティの値が(ここでは、文字列$ [「ナット」] [「ニーズ」])を教えてくれる===
以上。上記の2番目$ref
と2番目も同様です===
。
適切なディープイクイティテストを使用してみましょう(つまりdeepGraphEqual
、受け入れられた答えからAnders Kaseorgの関数この質問)を使用して、クローンが機能するかどうかを確認します。
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
今、シベリア:
JSON.Siberia.forestify(makeToolshed())
シベリアはネストされた構造ではなく、「クラシック」JSONを模倣しようとしません。オブジェクトグラフは「フラット」な方法で記述されます。オブジェクトグラフの各ノードはフラットツリー(整数のみの値を持つプレーンなキーと値のペアのリスト)に変わります。これは、.forest.
インデックス0のエントリです。ルートオブジェクトを見つけ、より高いインデックスで他のノードを見つけます。オブジェクトグラフ、および(フォレストのツリーのいくつかのキーの)負の値は、atoms
配列(types配列を介して入力されますが、ここでは入力の詳細を省略します)を指します。すべての末端ノードはアトムテーブルにあり、すべての非末端ノードはフォレストテーブルにあり、オブジェクトグラフのノード数、つまりをすぐに確認できますforest.length
。それが機能するかどうかをテストしましょう:
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
比較
後でセクションを追加します。