Como serializar o nó DOM para JSON mesmo se houver referências circulares?

Eu quero serializar o nó DOM ou até mesmo a window inteira para JSON.

Por exemplo:

  >> 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 

O problema é que o JSON não suporta referências circulares por padrão.

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

window e nós DOM tem muitos deles. window === window.window como o document.body.ownerDocument === document .

Além disso, o JSON.stringify não serializa funções, portanto, isso não é o que estou procurando.

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":"#"}} 

Bom, não é?

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

Bem, não é bom o suficiente para mim.

Por quê?

Eu estou tentando fazer tabela de compatibilidade do DOM para diferentes navegadores. Por exemplo, o Webkit suporta o atributo de espaço reservado e o Opera não, o IE 8 suporta o localStorage e o IE 7 não, e assim por diante.

Eu não quero fazer milhares de casos de teste. Eu quero fazer maneira genérica para testar todos eles.

Atualização, junho de 2013

Eu fiz um protótipo NV / dom-dom-dom.com .

http://jsonml.org/ leva em consideração uma gramática para converter elementos DOM XHTML em JSON. Um exemplo:

 
  • First Item
  • Second Item
  • Third Item

torna-se

 ["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" ] ] 

Ainda não o usei, mas pensando em usá-lo para um projeto onde eu quero pegar qualquer página da web e modificá-la usando mouache.js.

Você poderia atravessar o DOM e gerar uma representação de object JS puro e depois alimentá-lo ao serializador DojoX. Mas, primeiro você precisa decidir como planeja mapear elementos DOM, seus atributos e os nós de texto, sem ambigüidade, para objects JS. Por exemplo, como você representaria o seguinte?

  Some text   

Como isso?

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

Eu acho que a razão pela qual o DojoX não suporta imediatamente a serialização do DOM poderia ser exatamente isso: a necessidade de primeiro escolher um esquema para mapear DOM para objects JS. Existe um esquema padrão que pode ser empregado? Seu object JS simplesmente imitaria uma tree DOM sem nenhuma function? Eu acho que você tem que primeiro definir o que sua expectativa é de “serializar DOM para JSON”.

Eu encontrei isso e funcionou muito bem para mim quando eu estava tentando converter uma string XML em JSON.

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

Talvez isso ajude.

Parece que você tem que escrever por conta própria. Os dados serializados JSON também podem não ser a escolha perfeita para sua tarefa (tabela de compatibilidade DOM). Você provavelmente terá que iterar os objects por conta própria, verificar os tipos dos atributos e assim por diante.

 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( ... ) { ... } } ...