如何将DOM节点序列化为JSON,即使存在循环引用?
如何将DOM节点序列化为JSON,即使存在循环引用?
我想将DOM节点甚至整个window对象序列化为JSON。
例如:
>> serialize(document)
-> {
"URL": "http://stackoverflow.com/posts/2303713",
"body": {
"aLink": "",
"attributes": [
"getNamedItem": "function getNamedItem() { [native code] }",
...
],
...
"ownerDocument": "#" // 递归链接在此处
},
...
}
JSON.stringify()方法
JSON.stringify(window) // TypeError: 将循环引用转换成JSON
问题在于JSON默认不支持循环引用。
var obj = {}
obj.me = obj
JSON.stringify(obj) // TypeError: 将循环引用转换成JSON
window和DOM节点有许多循环引用。window === window.window以及document.body.ownerDocument === document。
此外,JSON.stringify不会序列化函数,所以这并不是我要寻找的。
dojox.json.ref
`dojox.json.ref.toJson()`可以轻松地序列化具有循环引用的对象:
var obj = {}
obj.me = obj
dojox.json.ref.toJson(obj); // {"me":{"$ref":"#"}}
不错,对吧?
dojox.json.ref.toJson(window) // Error: 无法序列化DOM节点
对我来说还不够好。
为什么?
我正在尝试为不同的浏览器制作DOM兼容性表格。例如,Webkit支持placeholder属性,而Opera不支持,IE 8支持localStorage而IE 7不支持,等等。
我不想制作成千上万个测试用例。我想找到一种通用的方法来测试它们。
更新,2013年6月
我制作了一个原型:NV/dom-dom-dom.com。
问题的出现原因是在将DOM节点序列化为JSON时,需要解决如何将DOM元素、属性和文本节点明确地映射到JS对象的问题。需要确定一个标准的映射方案,以便将DOM转化为JS对象。是否有一种标准的方案可以应用?你的JS对象是否只是简单地模拟了一个没有任何功能的DOM树?我认为你首先需要定义你对"将DOM序列化为JSON"的期望。
解决方法是首先遍历DOM树,并生成一个纯JS对象的表示形式,然后将其传递给DojoX序列化程序。下面是一个可能的解决方案:
function serializeDOM(node) { if (node.nodeType === Node.TEXT_NODE) { return node.nodeValue; } else { var obj = { tag: node.tagName, attributes: [], children: [] }; for (var i = 0; i < node.attributes.length; i++) { var attribute = node.attributes[i]; obj.attributes.push({ name: attribute.name, value: attribute.value }); } for (var i = 0; i < node.childNodes.length; i++) { var childNode = node.childNodes[i]; obj.children.push(serializeDOM(childNode)); } return obj; } } var serialized = serializeDOM(document.documentElement); console.log(JSON.stringify(serialized));
这个方法会遍历DOM树,将每个节点转化为一个JS对象。对于文本节点,直接返回节点的值。对于元素节点,创建一个包含标签名、属性和子节点的对象。通过递归调用,可以将整个DOM树转化为一个JS对象的层次结构。最后,使用JSON.stringify将JS对象转化为JSON字符串。
这样,无论是否存在循环引用,都可以将DOM节点序列化为JSON。通过定义一个明确的映射方案,可以将DOM元素、属性和文本节点转化为JS对象,并最终序列化为JSON。
在这个问题中,出现的原因是想要将DOM节点序列化为JSON,即将XHTML DOM元素转化为JSON格式。然而,由于存在循环引用的问题,直接将DOM节点序列化为JSON会导致循环引用的节点无法正确地转化为JSON。为了解决这个问题,可以使用第三方库http://jsonml.org/提供的方法来解析DOM节点。
这个库提供了一种将XHTML DOM元素转化为JSON的语法。例如,对于以下HTML代码:
- First Item
- Second Item
- Third Item
使用该库进行转化后的结果为:
["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" ]
]
虽然作者并未使用这个库,但是在一个需要将任意网页重新模板化的项目中,可以考虑使用这个库来实现。
通过使用这个库,我们可以解决DOM节点序列化为JSON时遇到的循环引用问题。这个库提供了一种语法,可以将DOM节点转化为JSON格式,并且可以处理循环引用的情况。因此,可以使用这个库来序列化包含循环引用的DOM节点为JSON格式,以便在项目中进行进一步的处理。
问题的原因是作者在尝试将XML字符串转换为JSON时遇到了困难。作者在搜索过程中找到了一个名为XMLObjectifier的工具,可以将XML转换为JSON。然而,作者发现该工具已经过时了。
这个问题可以通过以下解决方法来解决:
1. 通过网站SourceForge找到并下载XMLObjectifier工具。
2. 在代码中使用以下代码将XML字符串转换为JSON:XMLObjectifier.xmlToJSON(XMLObjectifier.textToXML(xmlString));