隨筆背景:在向后台請求數據之后,我們常常會拿到一串json格式.此時,為了方便查看key-value,程序猿們常常使用一些在線json格式化工具或者是類似於notepadd++這樣的工具進行轉換.今天筆者捋了捋思路,自己寫了一個格式化json數據的小插件.記錄於此.
1.在頁面上部署一個空白的div,可以向里面輸入json數據,方便轉化.
html代碼如下:
<div class="flexBox">
<div id="data2" contenteditable="true" style="height: 600px;flex: 8;overflow-y: scroll"></div>
<button style="flex: 1" id="jsonFormat2">JSON格式化</button>
</div>
注意:設置div的contenteditable屬性值為true,可以讓一個div變的可編輯.(之前我一直以為只有input家族或者是textarea才能編輯....)
頁面的截圖如下:

2.接下來是通過js代碼遍歷json對象,實現格式化.
我的思路是:json對象無疑就是鍵值對(key-value),我們可以先遍歷json對象的每個屬性(key),判斷屬性值(value)的類型,如果是一個object,采用一個方法處理,如果是一個非object,則直接展示,我們姑且把上述方法定義為moreInfo,如果遍歷到一個value的類型是Array(數組),那么我們再遞歸,繼續循環調用moreInfo方法,直到把每一個最小單位的鍵值對取出來.
那么我們怎么讓每一個鍵值對處於一個單行呢?這里我使用的是<p>標簽,將key-value包裹在<p>標簽即可.遞歸這一塊兒,說起來挺繞的,需要把思路理清,考慮到每一種情況,再進行對應的操作.
說了我的思路,接下來是js代碼部分:
var newEle='';
$('#jsonFormat2').on('click', function () {
var resData2=JSON.parse($('#data2').text());
$('#data2').html('');
newEle='';
for(var item in resData2){
if(typeof(resData2[item])!='object' || resData2[item]==null){
newEle+='<p><span class="title">'+item+'</span>: '+resData2[item]+',</p>';
}else{
moreInfo(resData2[item],item);
}
}
$('#data2').html(newEle);
})
上述代碼中:newEle是我們最終要展示的格式化后的json數據結構,設置按鈕的點擊事件,一次進行判斷處理.
接下來是比較關鍵的函數moreInfo了:
function moreInfo(obj,item){
if(obj instanceof Array){
newEle+='<p><span class="title">'+item+':['+'</span>'+'</p>';
for(var i=0;i<obj.length;i++){
if(typeof(obj[i])!='object'){
newEle+='<p><span class="title">'+obj[i]+',</span></p>';
}else{
moreInfo(obj[i],'')
}
}
newEle+='<p><span class="title">'+']'+'</span>'+',</p>';
}else if(typeof(obj)=='object' && !(obj instanceof Array)){
newEle+='<p><span class="title">'+item+'{'+'</span>'+'</p>';
for(var item in obj){
if(typeof(obj[item])!='object' || obj[item]==null){
newEle+='<p><span class="title">'+item+'</span>: '+obj[item]+',</p>';
}else{
moreInfo(obj[item],item)
}
}
newEle+='<p><span class="title">'+'},'+'</span>'+'</p>';
}else{
newEle+='<p><span class="title">'+obj+'</span>'+',</p>';
}
}
tips:雖然javascript的原生對象中,沒有Array這種,也就是通過typeof()無法的到一個Array,即使是typeof(["1","2"]),返回的也是object.但是通過obj instanceof Array可以判斷對象是否為數組類型.
3.最終的效果如下圖:


內容太多就不一一截圖了.
總結:最開始我在公司寫了大概40分鍾左右,但是在進入到moreInfo這個函數之后,始終無法將第二層的json對象中的鍵值對取出來,回家理清思路之后,解決了.原因有二:
1.第二層的對象有幾個是數組,對於數組這塊之前沒有做處理,數組的元素可能是對象,也可能只是一個string,而對象的內部有可能還有對象以及string.....,如此遞歸循環
2.在調用moreInfo函數時,我最開始是將newEle作為一個參數傳遞進去的,通過return的方法,再返回出去.但實際上失敗了,回家理清思路之后,就好了:
function moreInfo(obj,item,ele){
if(obj instanceof Array){
ele+='<p><span class="title">'+item+':['+'</span>'+'</p>';
for(var i=0;i<obj.length;i++){
if(typeof(obj[i])!='object'){
ele+='<p><span class="title">'+obj[i]+',</span></p>';
}else{
moreInfo(obj[i],'')
}
}
ele+='<p><span class="title">'+']'+'</span>'+',</p>';
}else if(typeof(obj)=='object' && !(obj instanceof Array)){
ele+='<p><span class="title">'+item+'{'+'</span>'+'</p>';
for(var item in obj){
if(typeof(obj[item])!='object' || obj[item]==null){
ele+='<p><span class="title">'+item+'</span>: '+obj[item]+',</p>';
}else{
moreInfo(obj[item],item)
}
}
ele+='<p><span class="title">'+'},'+'</span>'+'</p>';
}else{
ele+='<p><span class="title">'+obj+'</span>'+',</p>';
}
}
應該是在moreInfo函數內部再次調用moreInfo時,ele沒有傳遞出去,導致newEle沒有發生變化.
當然這個小插件還是有瑕疵的,比如說在對於對象結尾的那個逗號進行判斷時,還需要優化.
ps:今天我覺得講解的夠詳細了額,博客園審核的小編們,你們再將我的博客移出博客園首頁的話,就說不過去了吧~ 0 0
