使用jsonpath_ng解析JSON时过滤后统计元素数量异常问题
jsonpath_ng统计过滤元素数量不符合预期的问题
问题重现
使用jsonpath_ng过滤JSON数据后,尝试用.len统计元素数量,结果返回字符串长度而非元素个数:
import json from jsonpath_ng.ext import * data_json = """ { "some_key":"some_value", "level_1":[{ "level_2_name" : "abc", "level_2_attr" : "123" }, { "level_2_name" : "def", "level_2_attr" : "123" }, { "level_2_name" : "ghi", "level_2_attr" : "123" } ] } """ data_dict = json.loads(data_json) # 原表达式返回字符串"abc"的长度3,而非预期的1 path_expr = "$.level_1[? level_2_name == 'abc']['level_2_name'].`len`" val_lst = parse(path_expr).find(data_dict) for item in val_lst: print(item.value) # 输出3
原因分析
不是库的bug,是表达式写法错误:
- 原表达式中
['level_2_name']会把过滤后的对象列表提取为单个字符串元素的列表(即["abc"]) .len在这里会作用于列表中的每个字符串元素,取字符串的长度("abc"的长度是3),而非作用于整个列表统计元素数量
正确的原生解决方案
要统计过滤后的元素数量,需要让.len作用于过滤后的对象列表,而不是提取字段后的字符串列表。调整表达式如下:
# 正确表达式:直接对过滤后的对象列表取长度 path_expr = "$.level_1[? level_2_name == 'abc'].`len`" val_lst = parse(path_expr).find(data_dict) for item in val_lst: print(item.value) # 输出1,符合预期
如果确实需要提取level_2_name后再统计数量,可以用嵌套的JSONPath语法,先把提取结果包装为一个列表,再取长度:
path_expr = "$.[$.level_1[? level_2_name == 'abc']['level_2_name']].`len`"
补充说明
- 虽然可以用Python原生
len()直接统计结果列表的长度,但上述调整后的表达式是jsonpath_ng的原生实现方式 - 针对大规模复杂JSON解析场景,jsonpath_ng的性能确实远不如Python原生逻辑,这是因为JSONPath需要额外处理语法解析、通用遍历逻辑,而原生代码可以针对性优化路径遍历,这种场景下更换原生方案是更合理的选择
内容的提问来源于stack exchange,提问作者web profiler
相关产品推荐
相关产品推荐

