我编写了以下函数来遍历JSON结构数据,以找到提供的targetField
和路径pathArr
的值,但我正在努力从递归返回结果,因为值对于targetField可能不存在。
此函数使用名为 result 的全局变量来返回targetField的值,但是这可以转移到findValue()的下一次调用,它可能找不到值但是显示最后一个电话result
。所以我想知道在不使用全局变量result
的情况下解决此问题的最佳方法是什么。
如果调用findValue()找不到targetField的值,只需返回 null作为结果。
pathArr 类似["first_level", "second_level", "third_level"];
var result = null;
function findValue(jsonData, pathArr, targetField) {
if (pathArr.length == 0) {
result = targetField in jsonData ? jsonData[targetField] : result;
return result;
} else {
var curNode = pathArr.shift();
if (curNode in jsonData) {
jsonData = jsonData[curNode];
}
if (Array.isArray(jsonData)) {
jsonData.forEach(function(thisData) {
findValue(thisData, pathArr, targetField);
});
} else {
findValue(jsonData, pathArr, targetField);
}
}
return result;
}
修改 感谢所有回复的人。
使用unobf改进的代码,我使用此testData进行测试,但似乎只返回最后一个匹配:
var testData = {
"num_found" : 3,
"category" : "social",
"groups": [
{"group" : {
"source" : [{"id" : "testID1", "num": 10, "field": "sociaology", "sub-subject" : "socialeconomy"},
{"id" : "testID2", "num": 20, "field": "mathematics", "sub-subject": ""},
{"id" : "testID3", "num": 7, "field": "biology", "sub-subject" : ""}
],
"identifier" : "shelf-01-E-XW1"
}},
{"group" : {
"source" : [{"id" : "testID4", "num": 50, "field": "sociaology2", "sub-subject" : ""},
{"id" : "testID5", "num": 44, "field": "mathematics2", "sub-subject": ""},
{"id" : "testID6", "num": 75, "field": "biology2", "sub-subject" : "european studies2"}
],
"identifier" : "shelf-02-W-EW3"
}},
{"group" : {
"source" : [{"id" : "testID7", "num": 59, "field": "sociaology3", "sub-subject" : "socialeconomy3"},
{"id" : "testID8", "num": 47, "field": "mathematics3", "sub-subject": ""},
{"id" : "testID9", "num": 76, "field": "biology3", "sub-subject" : "european studies3"}
],
"identifier" : "shelf-03-W-GW5"
}}
]
};
我发现我必须改变这行代码
return {value : result};
到
return result;
测试
for (var i = 0; i < testData.groups.length; i++) {
var value = findValue(testData.groups[i], ["group", "source"], "sub-subject");
console.log("found value: " + value);
}
答案 0 :(得分:1)
从根本上说,函数中的所有路径都必须返回一个值。目前,还有一条路径不是forEach
所采用的路径:
jsonData.forEach(function(thisData) {
findValue(thisData, pathArr, targetField);
});
在那里,您可能需要some
(这样您可以在找到它时停止)和一个可以设置为找到值的变量,例如:
var retval;
和
jsonData.some(function(thisData) {
retVal = findValue(thisData, pathArr, targetField);
return !!retVal; // Stops the `some` loop, doesn't exit `findValue`
});
if (retVal) {
return retVal;
}
附注:您不想在功能之外声明result
,没有必要。该功能可以完全独立。这是一个自包含的版本,例如:
function findValue(jsonData, pathArr, targetField) {
var result = null;
if (pathArr.length == 0) {
result = targetField in jsonData ? jsonData[targetField] : null;
} else {
var curNode = pathArr.shift();
if (curNode in jsonData) {
jsonData = jsonData[curNode];
}
if (Array.isArray(jsonData)) {
jsonData.some(function(thisData) {
result = findValue(thisData, pathArr, targetField);
return !!result; // Stops the `some` loop, doesn't exit `findValue`
});
} else {
result = findValue(jsonData, pathArr, targetField);
}
}
return result;
}
注意:我没有对代码进行全面审核,只看了一下返回值。
答案 1 :(得分:1)
以下是包含一些测试数据的解决方案
function findValue(jsonData, pathArr, targetField) {
var result = null;
if (pathArr.length == 0 && jsonData.hasOwnProperty(targetField)) {
result = targetField in jsonData ? jsonData[targetField] : result;
return { value : result};
} else {
jsonData = jsonData[pathArr.shift()]
if (Array.isArray(jsonData)) {
jsonData.forEach(function(thisData) {
result = findValue(thisData, pathArr, targetField);
});
} else if (typeof jsonData !== 'undefined') {
return findValue(jsonData, pathArr, targetField);
}
}
return result;
}
testData = [{
hello : 'hello',
pathArr: []
}, {
child : {
hello : false
},
pathArr: ['child']
}, {
child : {
hello : null
},
pathArr: ['child']
}, {
child: {
child: {
hell: 'hell'
}
},
pathArr: ['child', 'child']
}];
testData.forEach(function (json) {
console.log(findValue(json, json.pathArr, 'hello'));
});