如何優雅的取出多層級JSON最深處的值


背景描述:

一般我們在遇到這樣的JSON時:

const json = {
user: {
posts: [
{ title: 'A',
comments: [ 'Hello!', 'Interesting...' ]
},
{ title: 'B',
comments: [ 'Ok' ]
},
{ title: 'C',
comments: []
}
],
comments: [...]
}
}

需要取出里面的值得這樣寫:

json.user &&
json.user.posts &&
json.user.posts[0] &&
json.user.posts[0].comments

一般思路:對於取不確定層次的深層值,我們首先想到的是使用遞歸函數,我要獲取的值就需要一個路徑來表示,路徑可以用數組來標記,如果是數組,我們還需要一個索引來指引,然后我們可以通過遞歸逐層取值,當路徑參數path長度為0時,認為取值完畢,返回結果;
方法一:使用遞歸函數
function isJson(obj){
  var isjson = typeof(obj) == "object" && Object.prototype.toString.call(obj).toLowerCase() == "[object object]" && !obj.length;
  return isjson;
}
var getJSONValue = (function f(path, obj){
//確保初始值為json
if(arguments.length === 2 && !isJson(obj)){
return console.log("第二個參數必須是一個JSON對象")
}
if(arguments.length === 2 && path.length === 0){
return console.log("數組參數長度不能為0")
}
if (arguments.length < 2){
return console.log("需要兩個參數");
}
if(!Array.isArray(path)){
return console.error("第一個參數請使用數組");
}else if(arguments.length === 2 && path.length === 0){
return console.error("數組參數長度不能為0")
}
//獲取值
var result = obj[path[0]];
path.shift();
if(!path.length){
return result;
}else{
return f(path,result,false);//增加false參數以保證只在首次遞歸判斷類型
}
});

var value = getJSONValue(['user','posts','comments','details','1'],json);//不輸出結果且阻塞下面運行,控制台報錯"Cannot read property '1' of undefined"
var value = getJSONValue(['user','posts','comments',1],json);//輸出結果:“Interesting”(假定上面代碼沒有阻塞)
以上方法通用性不高,限制了第二個參數必須為json才能使用,且沒有容錯機制,遇到錯誤會報錯。
於是繼續優化:
方法二:使用while
  
var getJSONValue = function(path, obj){
if(!Array.isArray(path)){
return console.error("第一個參數請使用數組形式");
}
var len = path.length;
var i = 0;
var str;
while(len){
str = path[i];
obj = obj[str];
// console.log('第'+(i+1)+'次取到',obj,'參數是',path[i])
if((obj === undefined || obj === null) && len !==0){
console.log('取值有錯誤,請確認傳入的第'+(i+1)+'個參數“'+path[(i)]+'”是否正確')
return null
}
i++;
len--;
}
return obj;
};
var value = getJSONValue(['user','posts','comments','details','1'],json);//輸出結果:null 控制台輸出為:"取值有錯誤,請確認傳入的第4個參數“details”是否正確"
var value1 = getJSONValue(['user','posts','comments',1],json);//輸出結果:“Interesting”
方法三:使用for循環
  
var getJSONValue = function(path, obj){
if(!Array.isArray(path)){
return console.error("第一個參數請使用數組");
}
var len = path.length;
for(var i = 0; i<len ;i++){
obj = obj[path[i]];
if(obj === undefined || obj === null){
return null
}
}
return obj
};

for使用大篇幅的底層運算描述,從而掩蓋了coder的本質用意。

相比之下foreach可讀性要強得多。

從而得出如下取出多層級JSON最深處的值的最優雅的方式:

方法四:使用forEach


var getJSONValue = function(path, obj){
  path.forEach(function(el){
    try{
      obj = obj[el]
    }catch(e){
      obj = null
    };
  });
  return obj
};


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM