web-dev-qa-db-fra.com

Comment sérialiser un nœud DOM en JSON même s'il existe des références circulaires?

Je veux sérialiser le nœud DOM ou même window entier en JSON.

Par exemple:

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

Le problème est que JSON ne prend pas en charge les références circulaires par défaut.

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

window et les nœuds DOM en ont beaucoup. window === window.window comme volonté que document.body.ownerDocument === document.

Aussi, JSON.stringify ne sérialise pas les fonctions, ce n'est donc pas ce que je recherche.

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

Bon, non?

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

Eh bien, ce n'est pas assez bon pour moi.

Pourquoi?

J'essaie de créer un tableau de compatibilité DOM pour différents navigateurs. Par exemple, Webkit prend en charge l'attribut d'espace réservé et Opera ne le fait pas, IE 8 prend en charge localStorage et IE = 7 non, et ainsi de suite.

Je ne veux pas faire des milliers de cas de test. Je veux créer un moyen générique pour les tester tous.

Mise à jour, juin 2013

J'ai fait un prototype NV/dom-dom-dom.com.

48
NVI

http://jsonml.org/ prend une photo d'une grammaire pour convertir des éléments DOM XHTML en JSON. Un un exemple:

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

devient

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

Je ne l'ai pas encore utilisé, mais je pense à l'utiliser pour un projet où je veux prendre n'importe quelle page Web et le reformater à l'aide de moustache.js.

13
Josh Dzielak

Vous pouvez potentiellement traverser le DOM et en générer une pure représentation d'objet JS, puis le nourrir dans le sérialiseur DojoX. Mais, vous devez d'abord décider comment vous prévoyez de mapper les éléments DOM, leurs attributs et les nœuds de texte, sans ambiguïté, aux objets JS. Par exemple, comment représenteriez-vous les éléments suivants?

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

Comme ça?

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

Je pense que la raison pour laquelle DojoX ne prend pas immédiatement en charge la sérialisation DOM pourrait être exactement la suivante: la nécessité de choisir d'abord un schéma pour mapper DOM aux objets JS. Existe-t-il un schéma standard qui pourrait être utilisé? Votre objet JS imiterait-il simplement une arborescence DOM sans aucune fonction? Je pense que vous devez d'abord définir ce que vous attendez de la "sérialisation du DOM en JSON".

5
Ates Goral

J'ai trouvé this et cela a très bien fonctionné pour moi lorsque j'essayais de convertir une chaîne XML en JSON.

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

Peut-être que cela vous aidera.

4
Matthew Taylor

Il semble que vous deviez l'écrire vous-même. Les données sérialisées JSON peuvent également ne pas être le choix parfait pour votre tâche (tableau de compatibilité DOM). Vous devez probablement itérer les objets par vous-même, vérifier les types d'attributs, etc.

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