接獲回報,前幾天釋出的地址輸入輔助元件在IE8上爆炸了,使用loalStorage儲存資料物件的JSON字串時,彈出"記憶體不足"錯誤。

追蹤後,發現問題源於IE8在JSON.stringify()轉換資料物件時,很機車地將中文字元全部換成UCN(Univeral Character Name,即\u1234、\u4e2d這種格式)。用IE Dev Tools即可印證明:

由於地址資料有滿滿的中文,在經過UCN轉換的蹂躪後,大小由1MB爆增到6MB,超出localStorage的容量上限,導致程式錯誤。

轉JSON字串時,應不應該對Unicode文字進行編碼呢? 依據JSON規格: Any UNICODE character except " or \ or control character 都應視為有效字元,故理論上中文字元並不需要Escape處理!


(圖檔來源: http://json.org/)

比較其他瀏覽器的做法:

IE9,沒轉!

IE10,沒轉!

Chrome,沒轉!

Firefox,沒轉!

很好,大家都不轉,就只有IE8會雞婆轉碼是怎樣?? (捏碎滑鼠) 算算這已是IE8原生JSON第三次搗蛋! (前科1前科2)

暫時想不到更好解法,我的因應之道是用var badJsonStringify = JSON.stringify("中").length > 3;偵測JSON.stringify()是否雞婆把"中"轉成"\u4e2d",如果是討厭的IE8,就不用原生JSON,改用json2.js提供的JSON.stringify();但因json2.js偵測有原生JSON物件時會自行迴避,我改了一個json2ext.js版本,將物名更名為JSON2提供服務。解法不怎麼漂亮,但問題有解,待有更好的點子時再改進。


Comments

# by Dennis

如果能確保Json Object內容安全的話 用eval也可以直接轉掉 eval("var str = '" + JSON.stringify({"Test":"中文ABC"}) + "';"); alert(str);

# by Jeffrey

to Dennis, 感謝建議,可惜這個案例需要將物件轉成JSON字串(取代IE8原生JSON的雞婆行為),eval這招就幫不上忙了。

# by xx

我拿到一个api返回的json,json内容是中文的unicode。 而在IE8无法正常显示unicode为中文,恼火啊! 有遇到过吗?

# by Jeffrey

to xx, IE8的原生JSON處理中文邏輯獨樹一格 orz 我建議可取回原始JSON字串(但得先確認取回的中文沒變亂碼),改用json2.js提供的parse功能解析。

# by Charles

或者是多繞一圈,把 中文字串先用 encodeURIComponent() 進行 URI 編碼,再把 JSON.stringify() 運算的結果,用 decodeURIComponent() 進行 URI 解碼

# by Will

try{ if(JSON.stringify('中').length > 3){ delete JSON; } }catch(ex){ }

# by niq

// 这样ok? if(JSON.stringify('中’) > 3) { JSON.stringifyie8 = JSON.stringify; JSON.stringify = function(0) { eval("var rfx = '" + JSON.stringifyie8(o) + "';"); return rfx; } }

Post a comment