Как сериализовать узел DOM в JSON, даже если есть циклические ссылки? - PullRequest
48 голосов
/ 21 февраля 2010

Я хочу сериализовать узел 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

Я сделал прототип NV / dom-dom-dom.com .

Ответы [ 4 ]

13 голосов
/ 13 марта 2011

http://jsonml.org/ делает снимок грамматики для преобразования элементов DOM XHTML в 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" ]
]

Пока не использовал его, но думаю об использовании его для проекта, где я хочу взять любую веб-страницу и повторно шаблонировать ее, используя mustache.js.

5 голосов
/ 21 февраля 2010

Вы могли бы потенциально пройти 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».

4 голосов
/ 21 октября 2010

Я нашел это , и он отлично работал для меня, когда я пытался преобразовать строку XML в JSON.

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

Может быть, это поможет.

3 голосов
/ 21 февраля 2010

Похоже, вы должны написать это самостоятельно. Сериализованные данные 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( ... ) { ... }
}
...
...