即使有循环引用,如何将 DOM 节点序列化为 JSON?
Posted
技术标签:
【中文标题】即使有循环引用,如何将 DOM 节点序列化为 JSON?【英文标题】:How to serialize DOM node to JSON even if there are circular references? 【发布时间】:2011-01-19 05:02:24 【问题描述】:我想将 DOM 节点甚至整个 window
序列化为 JSON。
例如:
>> serialize(document)
->
"URL": "http://***.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
不序列化函数,所以这不是我要找的。p>
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 年 6 月更新
我做了一个原型NV/dom-dom-dom.com。
【问题讨论】:
我正在尝试为不同的浏览器制作 DOM 兼容性表。 您希望如何对 DOM 节点进行序列化?你想从 DOM 节点获得什么信息? Gumbo,我刚刚添加了示例。现在清楚了吗? FWIW,我仍然不明白序列化为 JSON 是如何帮助您以“通用方式”测试兼容性的。 我需要区分不同浏览器的整个window
对象。如果不将window
序列化为 JSON 之类的东西,我不知道该怎么做。
【参考方案1】:
我找到了this,当我尝试将 XML 字符串转换为 JSON 时,它对我非常有用。
XMLObjectifier.xmlToJSON(XMLObjectifier.textToXML(xmlString));
也许会有所帮助。
【讨论】:
为了快速搜索xmlobjectifier jquery
,脚本已移至 SourceForge。但是,我发现它有点过时了。【参考方案2】:
http://jsonml.org/ 尝试将 Xhtml DOM 元素转换为 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 重新模板化的项目。
【讨论】:
【参考方案3】:您可能会遍历 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】:看起来你必须自己写。 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( ... ) ...
...
【讨论】:
我已经在console._source_of()
github.com/NV/console.js/blob/gh-pages/console.js#L29-84 中做了类似的事情,但它不处理循环引用。看起来我需要从 dojox.json.ref 中获取算法并根据我的需要采用它。以上是关于即使有循环引用,如何将 DOM 节点序列化为 JSON?的主要内容,如果未能解决你的问题,请参考以下文章
将输出序列化为 JSON - ValueError:检测到循环引用
将输出序列化为 JSON - ValueError:检测到循环引用