web-dev-qa-db-ja.com

循環参照がある場合でも、DOMノードをJSONにシリアル化する方法は?

DOMノードまたはwindow全体をJSONにシリアル化します。

例えば:

 >> serialize(document)
    -> {
      "URL": "http://stackoverflow.com/posts/2303713",
      "body": {
        "aLink": "",
        "attributes": [
          "getNamedItem": "function getNamedItem() { [native code] }",
          ...
        ],
        ...
        "ownerDocument": "#" // recursive link here
      },
      ...
    }

JSON.stringify()

JSON.stringify(window) // TypeError: Converting circular structure to JSON

問題は、JSONはデフォルトで循環参照をサポートしていないことです。

var obj = {}
obj.me = obj
JSON.stringify(obj) // TypeError: Converting circular structure to JSON

windowおよびDOMノードにはそれらの多くがあります。 window === window.windowと同様にdocument.body.ownerDocument === document

また、JSON.stringifyは関数をシリアル化しないため、これは私が探しているものではありません。

dojox.json.ref

 `dojox.json.ref.toJson()` can easily serialize object with circular references:

    var obj = {}
    obj.me = obj
    dojox.json.ref.toJson(obj); // {"me":{"$ref":"#"}}

いいですね。

 dojox.json.ref.toJson(window) // Error: Can't serialize DOM nodes

私には十分ではありません。

どうして?

さまざまなブラウザーのDOM互換性テーブルを作成しようとしています。たとえば、Webkitはプレースホルダー属性をサポートし、Operaはサポートしません、IE 8はlocalStorageおよびIEをサポートします= 7はそうではありません。

何千ものテストケースを作りたくありません。それらをすべてテストするための一般的な方法を作りたいです。

更新、2013年6月

プロトタイプを作成しましたNV/dom-dom-dom.com.

48
NVI

http://jsonml.org/ は、XHTML DOM要素をJSONに変換するための文法を試します。例:

<ul>
    <li style="color:red">First Item</li>
    <li title="Some hover text." style="color:green">Second Item</li>
    <li><span class="code-example-third">Third</span> Item</li>
</ul>

になる

["ul",
    ["li", {"style": "color:red"}, "First Item"],
    ["li", {"title": "Some hover text.", "style": "color:green"}, "Second Item"],
    ["li", ["span", {"class": "code-example-third"}, "Third"], " Item" ]
]

まだ使用していませんが、Webページを取得し、mustache.jsを使用して再テンプレート化するプロジェクトで使用することを検討しています。

13
Josh Dzielak

潜在的にDOMをトラバースし、その純粋なJSオブジェクト表現を生成してから、DojoXシリアライザーに渡すことができます。ただし、最初にDOM要素、その属性、およびテキストノードをあいまいさなしにJSオブジェクトにマップする方法を決定する必要があります。たとえば、以下をどのように表現しますか?

<parent attr1="val1">
  Some text
  <child attr2="val2"><grandchild/></child>
</parent>

このような?

{
    tag: "parent",
    attributes: [
        {
            name: "attr1",
            value: "val1"
        }
    ],
    children: [
        "Some text",
        {
            tag: "child",
            attributes: [
                {
                    name: "attr2",
                    value: "val2"
                }
            ],
            children: [
                { tag: "grandchild" }
            ]
         }
     ]
 }

DojoXがすぐにDOMシリアル化をサポートしない理由は、まさにこれであると思う:最初にDOMをJSオブジェクトにマッピングするスキームを選択する必要がある。採用できる標準的なスキームはありますか?あなたのJSオブジェクトは、関数なしでDOMツリーを単純に模倣しますか? 「DOMをJSONにシリアル化する」ことから期待することを最初に定義する必要があると思います。

5
Ates Goral

this を見つけたので、XML文字列をJSONに変換しようとしていたとき、私にとってはうまくいきました。

XMLObjectifier.xmlToJSON(XMLObjectifier.textToXML(xmlString));

たぶんそれが役立つでしょう。

4
Matthew Taylor

自分で書く必要があるようです。 JSONシリアル化データは、タスクに最適な選択肢ではない場合もあります(DOM互換性テーブル)。おそらく自分でオブジェクトを反復処理し、属性のタイプを確認する必要があります。

var functions = [];
var strings = [];
for( var key in window ) {
    if( typeof window[key] == 'string' ) {
        strings[strings.length] = key;
    } else if( typeof window[key] == 'function' ) {
        functions[functions.length] = key;
    } else if( ... ) { ... }
}
...
3
Frunsi