Python中jsonpath-ng过滤与值提取问题及使用咨询
语法与原理说明
1. 学习路径
jsonpath-ng是JSONPath规范的Python原生实现,核心逻辑是将JSONPath表达式解析为抽象语法树,再递归遍历目标JSON对象完成节点匹配。最准确的学习材料是库自带的单元测试用例,覆盖了所有语法的实现细节和使用示例,比零散的第三方资料更贴合实际使用。
2. 两种访问格式的区分
- 点语法(
jpath.key):仅适用于属性名是合法标识符(不含特殊字符、空格、不以数字开头)的场景,all()是类方法,用于返回当前节点下的所有子节点集合 - 方括号语法(
jpath[key]):适用于属性名含特殊字符、属性名是变量、访问数组索引的场景,[*]是通配符,用于匹配数组的所有元素或对象的所有子属性
示例:你代码中动态拼接ID的路径units.'{curr_id}'可以写为更规范的units[{curr_id}],无需额外加单引号包裹变量。
3. 过滤从句语法
过滤从句格式为[? 过滤表达式],直接追加在需要过滤的节点后:
- 用
@指代当前正在匹配的节点 - 支持
==/!=/>/<等比较运算符,&&/||逻辑运算符
示例1:过滤所有已激活的技能:Abilities[?Activated == true]
示例2:过滤GearTier大于等于3的升级项:Levels[?Requirements.GearTier >= 3]
代码优化方案
首先定义道具ID到位置的映射,避免硬编码判断:
# 道具ID对应req字段的位置索引,依次对应req2到req5及预留位 ITEM_POS_MAP = { 133: 0, 13: 1, 3883066061505188: 2, 6221535176831871: 3, 4010306196179359: 4 }
优化后的遍历逻辑,减少冗余JSONPath解析,逻辑更清晰:
from jsonpath_ng import parse total = [] # 一次匹配所有unit节点,无需单独查询ID unit_expr = parse("units.*") for unit_match in unit_expr.find(data): unit_data = unit_match.value toon_id = unit_data["ID"] # 遍历当前角色的所有技能 for ability in unit_data.get("Abilities", []): ability_id = ability.get("ID", "") ability_name = ability.get("NameKey", "") ability_type = ability.get("AbilityType", "") # 遍历技能的所有升级等级 for level in ability.get("Levels", []): # 拼接target字段 target_list = [] if level.get("TargetSelf"): target_list.append("Self") if level.get("TargetAlly"): target_list.append("Ally") if level.get("TargetEnemy"): target_list.append("Enemy") target = ",".join(target_list) # 获取gear要求,缺省为0 gear_req = level.get("Requirements", {}).get("GearTier", 0) # 初始化5个req字段均为0,自动统一长度 req_list = [0] * 5 recipe = level.get("Recipe") if recipe: for ingredient in recipe.get("Ingredients", []): item_id = ingredient.get("ItemID") count = ingredient.get("Count", 0) if item_id in ITEM_POS_MAP: req_list[ITEM_POS_MAP[item_id]] = count # 拼接完整行,总长度固定为11,无需手动对齐 row = [toon_id, ability_id, ability_name, ability_type, target, gear_req] + req_list total.append(row)
优化点说明
- 仅执行一次JSONPath解析,后续直接操作Python原生对象,性能远高于重复解析路径匹配
- 所有字段取值用
get方法加默认值,兼容字段缺失、值为null的场景 - 提前初始化固定长度的req列表,无需手动补0对齐
- 去掉冗余的临时变量,避免索引操作导致的数据错位
内容的提问来源于stack exchange,提问作者Nir Abutbul
相关产品推荐
相关产品推荐

