You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python中使用可变键导航JSON数据?

实现类似data.get(key)的JSON路径取值功能

假设我们在Python中有这样的JSON数据存在变量data里:

{
  "print": {
    "ams": { "exists": 1},
    "fan_speed": 29,
    "reports": [
      {"name": "foo"},
      {"name": "bar"}
    ]
  }
}

现在有一个存储目标访问路径的变量key,比如print.fan_speed、print.ams.exists、print.reports[0].name,想要实现类似data.get(key)的便捷取值功能,最优的实现方式是什么?


这需求太实用了!我平时处理嵌套JSON的时候也经常想有这么个便捷方法,下面给你几个靠谱的实现思路,从无依赖的手写版到成熟第三方库都涵盖了:

方案一:手写轻量解析器(无依赖,首推)

这是最灵活且不需要额外安装库的方式,核心思路是把路径字符串拆分成一个个访问节点,然后逐个遍历嵌套结构,还能模仿dict.get支持默认值:

def get_nested_value(data, key, default=None):
    current = data
    # 拆分路径节点,处理数组索引和普通键
    nodes = []
    for part in key.split('.'):
        if '[' in part and ']' in part:
            # 解析类似reports[0]这样的数组节点
            arr_name, idx_str = part.split('[')
            idx = int(idx_str.rstrip(']'))
            nodes.append(arr_name)
            nodes.append(idx)
        else:
            nodes.append(part)
    
    try:
        for node in nodes:
            current = current[node]
        return current
    except (KeyError, IndexError, TypeError):
        # 路径不存在时返回默认值
        return default

用法示例

data = {
  "print": {
    "ams": { "exists": 1},
    "fan_speed": 29,
    "reports": [
      {"name": "foo"},
      {"name": "bar"}
    ]
  }
}

print(get_nested_value(data, "print.fan_speed"))  # 输出 29
print(get_nested_value(data, "print.ams.exists"))  # 输出 1
print(get_nested_value(data, "print.reports[0].name"))  # 输出 'foo'
print(get_nested_value(data, "print.reports[2].name", default="unknown"))  # 输出 'unknown'

这个方案的优点是零依赖、逻辑透明、易扩展,完全能满足绝大多数简单路径取值的需求。

方案二:利用第三方成熟库(复杂场景首选)

如果你的项目需要处理更复杂的路径(比如通配符、条件过滤、数组切片),可以用专门的JSON路径库,比如jmespath:

首先安装库:

pip install jmespath

然后用法超级简洁:

import jmespath

# 简单路径取值
print(jmespath.search("print.reports[0].name", data))  # 输出 'foo'
# 支持更复杂的表达式,比如提取所有reports的name字段
print(jmespath.search("print.reports[*].name", data))  # 输出 ['foo', 'bar']

jmespath支持非常丰富的路径语法,适合处理复杂的JSON查询场景,但如果只是简单的路径取值,手写轻量版足够用了。

方案三:用reduce简化手写逻辑

如果你喜欢更紧凑的代码,可以用functools.reduce配合operator.getitem来实现,本质和方案一逻辑一致:

from functools import reduce
import operator

def get_nested_value(data, key, default=None):
    def parse_node(part):
        if '[' in part and ']' in part:
            arr_name, idx_str = part.split('[')
            return [arr_name, int(idx_str.rstrip(']'))]
        return [part]
    
    # 把所有路径节点扁平化
    nodes = []
    for part in key.split('.'):
        nodes.extend(parse_node(part))
    
    try:
        return reduce(operator.getitem, nodes, data)
    except (KeyError, IndexError, TypeError):
        return default

总结

  • 简单路径取值:方案一的手写轻量版是最优解,零依赖、易维护、性能足够;
  • 复杂JSON查询:用jmespath这类成熟库更高效。

内容的提问来源于stack exchange,提问作者K20GH

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 17:50:23