在实际开发场景中,JSON是最常用的数据交换格式之一,很多时候我们会遇到多层嵌套的JSON结构,比如接口返回的复杂业务数据、前端配置化文件的存储内容等。当需要从这类嵌套结构中提取某个指定键对应的所有值,而不是仅获取第一层的结果时,手动逐层遍历不仅耗时,还容易遗漏深层数据,因此需要一套高效的提取方案。

核心实现思路
递归遍历法
递归是最直观的实现方式,核心逻辑是遍历当前JSON对象的每一个属性:如果当前属性是目标键,就收集对应的值;如果当前属性的值是对象或数组,就递归调用遍历函数继续处理。这种方式的代码逻辑清晰,适合嵌套深度不确定的场景。
栈迭代法
递归虽然简单,但如果JSON嵌套深度过大,可能会出现栈溢出的问题。栈迭代法通过手动维护一个栈结构来存储待处理的元素,避免函数调用栈过深,适合处理超深层嵌套的JSON数据,稳定性更强。
JavaScript实现示例
以下是使用递归和栈迭代两种方式实现的提取函数:
// 递归方式提取嵌套JSON中指定键的所有值
function extractValuesByKeyRecursive(jsonObj, targetKey) {
const result = [];
// 定义递归遍历函数
function traverse(obj) {
if (typeof obj !== 'object' || obj === null) {
return;
}
// 处理数组类型
if (Array.isArray(obj)) {
for (let item of obj) {
traverse(item);
}
return;
}
// 遍历对象属性
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
// 如果当前键是目标键,收集值
if (key === targetKey) {
result.push(obj[key]);
}
// 如果属性值是对象或数组,继续递归
if (typeof obj[key] === 'object' && obj[key] !== null) {
traverse(obj[key]);
}
}
}
}
traverse(jsonObj);
return result;
}
// 栈迭代方式提取嵌套JSON中指定键的所有值
function extractValuesByKeyIterative(jsonObj, targetKey) {
const result = [];
// 初始化栈,放入根对象
const stack = [jsonObj];
while (stack.length > 0) {
const current = stack.pop();
if (typeof current !== 'object' || current === null) {
continue;
}
// 处理数组类型
if (Array.isArray(current)) {
for (let item of current) {
stack.push(item);
}
continue;
}
// 遍历对象属性
for (let key in current) {
if (current.hasOwnProperty(key)) {
if (key === targetKey) {
result.push(current[key]);
}
if (typeof current[key] === 'object' && current[key] !== null) {
stack.push(current[key]);
}
}
}
}
return result;
}
// 测试示例
const testJson = {
name: '测试数据',
age: 20,
info: {
hobby: '阅读',
score: {
math: 90,
english: 85
}
},
list: [
{ name: '子项1', age: 18 },
{ name: '子项2', age: 19 }
]
};
console.log('递归提取name的值:', extractValuesByKeyRecursive(testJson, 'name'));
console.log('迭代提取age的值:', extractValuesByKeyIterative(testJson, 'age'));
Python实现示例
Python中同样可以使用两种思路实现,代码风格更简洁:
# 递归方式提取嵌套JSON中指定键的所有值
def extract_values_recursive(json_obj, target_key):
result = []
def traverse(obj):
if not isinstance(obj, (dict, list)):
return
if isinstance(obj, list):
for item in obj:
traverse(item)
return
for key, value in obj.items():
if key == target_key:
result.append(value)
if isinstance(value, (dict, list)):
traverse(value)
traverse(json_obj)
return result
# 栈迭代方式提取嵌套JSON中指定键的所有值
def extract_values_iterative(json_obj, target_key):
result = []
stack = [json_obj]
while stack:
current = stack.pop()
if not isinstance(current, (dict, list)):
continue
if isinstance(current, list):
for item in current:
stack.append(item)
continue
for key, value in current.items():
if key == target_key:
result.append(value)
if isinstance(value, (dict, list)):
stack.append(value)
return result
# 测试示例
test_json = {
"name": "测试数据",
"age": 20,
"info": {
"hobby": "阅读",
"score": {
"math": 90,
"english": 85
}
},
"list": [
{"name": "子项1", "age": 18},
{"name": "子项2", "age": 19}
]
}
print("递归提取name的值:", extract_values_recursive(test_json, "name"))
print("迭代提取age的值:", extract_values_iterative(test_json, "age"))
方案对比与选择建议
我们可以通过下表对比两种实现方式的特点:
| 实现方式 | 时间复杂度 | 空间复杂度 | 适用场景 |
|---|---|---|---|
| 递归遍历法 | O(n),n为JSON元素总数 | O(d),d为JSON嵌套深度 | 嵌套深度适中、代码可读性要求高的场景 |
| 栈迭代法 | O(n),n为JSON元素总数 | O(n),最坏情况栈存储所有元素 | 嵌套深度极大、避免栈溢出的场景 |
实际开发中可以根据JSON的实际嵌套情况选择合适的方案,如果嵌套深度可控,优先选择递归法,代码更易维护;如果处理的是未知来源的复杂嵌套JSON,建议使用栈迭代法保证稳定性。