2

我有一个想要序列化为字符串的 JavaScript 对象:

key                     {...}       Object
    mandant             "00001"     String
    personalNummer      600235      Number

首先,我使用 JSON2,返回值为undefined. 使用JSON3,我得到一个TypeError并且行中的评论json3.js说:

// Cyclic structures cannot be serialized by `JSON.stringify`.

问题似乎是由json3.js中的以下几行引起的:

// Manually invoke the callback for the `constructor` property due to
// cross-environment inconsistencies.
if (isConstructor || isProperty.call(object, (property = "constructor"))) {
    callback(property);
}

但是应该没有循环,我显然无法找出到底发生了什么。

当我在调试时手动创建对象时,一切正常。

那么什么会引发错误呢?


编辑
我成功地准备了一个产生错误的场景:

  • 它只发生在具有兼容模式 IE7 和 IE8 的 IE9 中(Firefox 22 也可以)
  • 如果打开一个引用打开器窗口中的数据的新窗口,就会发生这种情况



*JSON_Cycle.html*:

    <script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.js"></script>
    <script type="text/javascript" src="http://bestiejs.github.io/json3/lib/json3.js"></script>
    <script>
    var dataGlobal = {mandant: "Hallo Welt!", personalNummer: 123456};
        $(function() {
            window.open("JSON_Cycle_Popup.html", 'popup');
        });
    </script>



*JSON_Cycle_Popup.html*:

<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script type="text/javascript" src="http://bestiejs.github.io/json3/lib/json3.js"></script>
<script>
    var dataGlobal = null;
    $(function() {
        dataGlobal = window.opener.dataGlobal;
        alert(JSON.stringify(dataGlobal));
    });
</script>
4

2 回答 2

1

根据您问题中的新信息,我现在可以解释正在发生的事情。

JSON_Cycle.html文件中,在初始化dataGlobal变量后添加以下行。

alert(typeof dataGlobal.constructor);

现在在JSON_Cycle_Popup.html中做同样的事情。注意到区别了吗?在 IE 上,第一个警报显示构造函数的类型为“函数”,但在弹出窗口中,相同的构造函数返回“对象”类型。

所以这是第一个问题。下一个问题来自 json3 枚举对象属性的方式。他们不只是使用常规的 for 循环,即for (property in object) .... 他们有很多代码试图检测不同浏览器实现之间的不一致,以生成一个在所有平台上返回相同结果的枚举器。

这个枚举器的作用之一是它为每个对象返回一个构造函数属性,即使在 for 循环中通常不会返回一个。这似乎完全没有必要,因为您显然不想在 json 对象中序列化构造函数。但我怀疑这段代码是从其他一些需要这种行为的项目继承的。

这两个问题的结合,意味着在序列化dataGlobal对象时,json3 将找到一个构造函数属性,它将尝试处理。然后在序列化该构造函数(它认为是另一个对象)时,它将找到另一个构造函数属性(再次看起来是一个对象)。如果不是为了下一个问题,这个过程将继续无穷无尽。

经过四级构造函数嵌套,函数指针循环。即:

dataGlobal.constructor.constructor.constructor.constructor ==
dataGlobal.constructor.constructor

我不知道为什么会这样,但在我测试过的所有浏览器上似乎都是这样。这意味着 json3 代码不会获得无限递归,而是检测到一个循环并抛出一个TypeError异常。

这就是你的错误的解释。IE 中的一个错误与 json3 属性枚举器的不必要的巧妙结合。

于 2013-07-22T19:06:58.613 回答
1

在序列化之前,我必须设置一个构造函数:

key.constructor = function() {};

编辑:
但这仅适用于对象!使用数组,我有类似的问题。但是这里上面的修复不起作用!

在这种情况下,在对实际 Array 进行字符串化时,将在索引 0 处打包到一个新 Array 中。有趣的是,实际 Array 的构造函数仍然是一个函数。但是:索引 1 和 2 上有两个额外的对象。这些对象又是对象。但似乎无法从 JSON 库外部进行操作。

我没有时间和精力把它弄清楚到底,或者修改和测试 JSON。所以我使用不优雅的方法将元素放入一个新元素中(不克隆 -> 结果将是相同的错误):

$.each(fahrzeuge, function() {
    zugNummern.push(this);
});

因为只有几个元素,它的性能并不昂贵,并且会做到。但如果有人会发布更好的解决方案,我会很高兴。

于 2013-07-16T09:57:27.183 回答