jq中如何引用对象动态键,实现自定义过滤器按传入键列表提取对象子集
自定义批量动态键提取过滤器的实现方案
核心问题拆解
迭代入参失效的本质原因,是jq的迭代操作会覆盖当前上下文的.值:如果直接对传入的键列表执行$keys[]遍历,.会被替换为列表内的每个字符串元素,再也无法引用最初传入的源对象,自然取不到对应键的值。
解决思路非常简单:提前把当前输入的源对象缓存为临时变量,再对传入的键列表做遍历,全程使用缓存的变量取值,就不会出现上下文丢失的问题。
构建动态键值对时,需要用($变量)的语法标记动态键名,jq会自动计算括号内表达式的值作为对象键,而不会把表达式本身当字面量键名。
完整可用的过滤器代码
def myFilter($keys): # 缓存当前输入的源对象,避免后续迭代覆盖上下文 . as $source # 遍历传入的键列表,逐次累加键值对到空对象中 | reduce $keys[] as $key ({}; . + { ($key): $source[$key] });
测试验证
按照给定的场景,执行完整命令的效果如下:
jq -n ' def myFilter($keys): . as $source | reduce $keys[] as $key ({}; . + { ($key): $source[$key] }); {name: "Chris", age: 25, city: "Chicago"} | myFilter(["name", "age"]) '
输出结果完全匹配预期:
{"name":"Chris","age":25}
常见衍生调整
如果需要跳过源对象中不存在的键,避免给结果集补null值,可以在累加逻辑里加存在性判断:
def myFilter($keys): . as $source | reduce $keys[] as $key ({}; if $source | has($key) then . + { ($key): $source[$key] } else . end );
内容的提问来源于stack exchange,提问作者Christopher Shroba
相关产品推荐
相关产品推荐

