JSON.stringify()可以產出一個object的JSON格式字串,此處將JSON.stringify()更進一步enhance,以避免object內有無窮循環連結的問題。
並不是每個瀏覽器的javascript都已經內建了JSON物件,為此stackoverflow上有人提供了JSON.stringify()程式碼,以解決這個問題。但該程式碼會有個問題:給如下的object a
a=[]
b={}
b.f1="good"
b.f2="nice"
b.parent= a
a.push(b)
a.push(a)
這個object a有個特殊情況是,a[0].parent會指回自己,a[1]也是指回自己。把這種含有無窮循環連結的物件送入傳統的JSON.stringify()後,將會導致無窮迴圈,因而程式產生錯誤。以下的增強版本會跳過「已處理過」的子物件,因而避掉前述的問題
// implement JSON.stringify serialization
// original source: http://stackoverflow.com/questions/4715373/json-object-undefined-in-internet-explorer-8-dom
var JSON = JSON || {};
JSON.stringify= function (obj,par) {
if (typeof par=='undefined' || par=='debug'){ // to initialize it
JSON.ii=0; // stringify iteration index
JSON.obj=[]; // array containing the object that had been processed by stringify
JSON.obj.push(obj);
JSON.debug= (par=='debug' && typeof par!='undefined' )
}
var t = typeof (obj);
if (t != "object" || obj === null) {
// simple data type
if (t == "string") obj = '"'+ obj.replace(/\\/ig,"\\\\").replace(/"/ig,'\\"').replace(/\n/ig,"\\n").replace(/\t/ig,"\\t") +'"';
return String(obj);
}
else {
// recurse array or object
var n, v, json = [];
var arr = (obj && Array.isArray(obj)); //seems better than arr = (obj && obj.constructor == Array);
for (n in obj) {
v = obj[n];
t = typeof(v);
if (t == "function") continue; // skip it, if the object is a function
if (t == "string") v = '"'+v.replace(/\\/ig,"\\\\").replace(/"/ig,'\\"').replace(/\n/ig,"\\n").replace(/\t/ig,"\\t") +'"';
else if (t == "object" && v !== null) {
if (JSON.obj.includes(v)){
if (JSON.debug){
try{
console.log("!!-recursive object detected and omitted: " + (arr? "array[" + n + "]": "object '" + n + "'"))
} catch(err){}
}
continue; // skip it, if the object had been processed
}
JSON.obj.push(v);
JSON.ii++
//if (JSON.ii++>100) return // turn on it, if you want to prevent it from infinite iteration
if (JSON.debug){
try{
if (arr)
console.log("[level:" + JSON.ii + "] array[" + n + "]")
else
console.log("[level:" + JSON.ii + " object]" + n)
} catch(err){}
}
v = JSON.stringify(v,"sub_object");
JSON.ii--
}
json.push((arr ? "" : '"' + n + '":') + String(v));
if (JSON.debug){
try{
console.log((arr ? "" : '"' + n + '":') + String(v))
} catch(err){}
}
} // for
return (arr ? "[" : "{") + String(json) + (arr ? "]" : "}");
}
}
測試結果如下(這是在Chrome執行的結果)
JSON.stringify(a)
"[{"f1":"good","f2":"nice"}]"
JSON.stringify(b)
"{"f1":"good","f2":"nice","parent":[]}"
a[0].parent指回自己,a[1]也是指回自己,所以都被跳過,而不會出現在JSON.stringify(a)的結果。
同樣地,b.parent[0]與b重複、b.parent[1]與b.parent重複,所以b.parent[0]和b.parent[1]都會被跳到,而使得b.parent在JSON.stringify(b)的結果中變成是empty array的呈現。
另外,此增強版本的JSON.stringify()還有一個debug功能,第二個參數設為"debug",就可以將stringify運作過程的一些資料顯示出來 (這是在Chrome執行的結果)
JSON.stringify(a,"debug")
VM501:43 [level:1] array[0]
VM501:55 "f1":"good"
VM501:55 "f2":"nice"
VM501:32 !!-recursive object detected and omitted: object 'parent'
VM501:55 {"f1":"good","f2":"nice"}
VM501:32 !!-recursive object detected and omitted: array[1]
"[{"f1":"good","f2":"nice"}]"