2013-07-16 38 views
2

我有一個JavaScript對象我想要序列作爲字符串:類型錯誤在週期的原因透過JSON.stringify()時

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); 
} 

但不應該有周期和我很明顯,他們無法知道究竟是怎麼回事。

當我在手工創建對象時調試一切正常。

那麼,什麼會引發錯誤?


編輯
我成功準備一個場景產生錯誤:

  • 它只是發生在IE9兼容性模式IE7和IE8(火狐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> 
+1

你能提供生成錯誤所需的最少代碼嗎? – user568109

+0

我很喜歡,但是手工創建這樣的對象時不會顯示問題。似乎只有當對象通過AJAX($ .post())加載時纔會出現。在服務器端,我使用Jackson來序列化PoJO。我將設置一個方案試圖挑起錯誤... –

+0

@MarvinEmilBrach鑑於數據是作爲JSON字符串從服務器返回的,爲什麼要將它轉換爲僅用於將其轉換回JSON字符串的對象再次? –

回答

1

序列化之前,我必須設置一個構造函數:

key.constructor = function() {}; 

編輯:
但這隻適用於對象!對於數組,我有類似的問題。但是這裏的上述修補程序不起作用!

在這種情況下,字符串化實際數組將被打包到索引0上的新數組中。有趣的是,實際數組的構造函數仍然是一個函數。但是:在索引1和2上還有兩個額外的對象,而這些對象又是一個對象。但似乎從JSON庫之外不可操縱。

我還沒有時間和精力來弄清楚它到底,還是修改和測試JSON。所以,我用的是unelegant方法把元素融入到一個新的(不是克隆 - >結果將是同樣的錯誤):

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

因爲目前只有少數幾個元素是在性能上沒有昂貴的,將做到這一點。但如果有人會發布更好的解決方案,我會很高興。

1

根據您問題中的新信息,我現在可以解釋發生了什麼。

在你JSON_Cycle.html文件時,dataGlobal變量被初始化後添加以下行。

alert(typeof dataGlobal.constructor); 

現在做同樣的事情在JSON_Cycle_Popup.html。注意區別?在IE中,第一個警告顯示構造函數的類型是「函數」,但在彈出窗口中,該構造函數返回一個「對象」類型。

所以這是第一個問題。接下來的問題來自json3枚舉對象屬性的方式。他們不只是使用常規循環,即for (property in object) ...。他們有很多代碼試圖檢測不同瀏覽器實現之間的不一致,以產生在所有平臺上都返回相同結果的枚舉器。

此枚舉器的其中一個影響是它爲每個對象返回一個構造函數屬性,即使通常不會在for循環中返回該屬性。這看起來完全沒有必要,因爲你顯然不想序列化json對象中的構造函數。但我懷疑這個代碼是從其他項目中繼承而來的,那些行爲是可取的。

這兩個問題的結合,意味着串行化dataGlobal對象時,json3是要找到一個構造屬性,它會嘗試過程。然後,當序列化的構造函數(它認爲是另一個對象)時,它將找到另一個構造函數屬性(又是它看起來是一個對象)。如果不是下一個問題,這個過程將繼續無窮無盡。

經過四個層次的構造函數嵌套,函數指針循環。即:

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

我不知道爲什麼是這樣,但它似乎對我測試過的所有瀏覽器都如此。這意味着,不是獲得無限遞歸,而是json3代碼檢測到一個週期並拋出TypeError異常。

所以這就是你的錯誤的解釋。 IE中的一個bug與json3屬性枚舉器部分的不必要的巧妙結合在一起。

+0

很好的答案(會做一個更好的問題比我的;))+1 ...今天我將花一兩個小時來設置一個測試場景,同時這樣做會爲您提供更多信息... –

+0

我已經嘗試使用**刪除**而不是分配一個空函數。但它不起作用。如果定義了構造函數,空函數確實存在問題,但是我懷疑在這種情況下問題根本就不會引發...... –

+0

@MarvinEmilBrach我已經重寫了我的答案,解釋了基於新信息發生的事情提供。 –