如何优雅的取出多层级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