Как сериализовать DOM node в JSON, даже если есть круговые ссылки?
Я хочу сериализовать DOM node или даже целую 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.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 поддерживает атрибут placeholder, а Opera - нет, IE 8 поддерживает localStorage
, а IE 7 - нет и т.д.
Я не хочу делать тысячи тестовых случаев. Я хочу сделать общий способ проверить их все.
Обновление, июнь 2013 г.
Я сделал прототип NV/dom-dom-dom.com.
Ответы
Ответ 1
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.
Ответ 2
Вы можете потенциально пересечь 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" }
]
}
]
}
Я думаю, что причина, по которой w580 не сразу поддерживает сериализацию DOM, может быть именно такой: необходимо сначала выбрать схему для сопоставления DOM с объектами JS. Существует ли стандартная схема, которая может быть использована? Будет ли ваш объект JS просто имитировать дерево DOM без каких-либо функций? Я думаю, вы должны сначала определить, каково ваше ожидание от "сериализации DOM к JSON".
Ответ 3
Я нашел это, и он отлично поработал у меня, когда я пытался преобразовать XML-строку в JSON.
XMLObjectifier.xmlToJSON(XMLObjectifier.textToXML(xmlString));
Возможно, это поможет.
Ответ 4
Похоже, вы должны написать это самостоятельно. Сериализованные данные 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( ... ) { ... }
}
...