如何用jq条件修改JSON内容并保留原结构?附常见问题解析
使用jq修改JSON数组对象的优化方案与常见问题解析
一、更简洁的jq写法
假设你的input.json结构如下:
{ "signal": [ {"name": "signal1", "nested": {"prop": "old_value"}}, {"name": "temperature", "nested": {"prop": "unchanged"}}, {"name": "signal5", "nested": {"prop": "old_value"}} ], "metadata": "保留原有内容" }
可以用这条更简洁的命令完成需求:
jq '.signal |= map(select(.name | contains("signal")) |= (.nested.prop = "CHANGED-" + (.name | match("\\d$").string)) // .)' input.json
写法说明:
.signal |= map(...):直接定位到signal数组,用map遍历并修改数组元素,修改后重新赋值回原字段,保证整体结构不变。select(.name | contains("signal")):精准筛选出name包含"signal"的对象。(.nested.prop = "CHANGED-" + (.name | match("\\d$").string)):提取name最后一位数字,拼接成目标字符串后赋值给.nested.prop。// .:确保不匹配筛选条件的对象原样保留,避免被过滤掉。
二、为什么之前的写法会输出多个JSON对象?
出现这种情况通常是以下两种原因:
- 直接遍历数组元素而非修改原数组:如果你的写法是类似
jq '.signal[] | select(.name | contains("signal")) | .nested.prop = ...',这种写法会直接遍历signal数组的每个元素,对匹配的元素单独修改后输出,而不会把修改后的元素放回原数组、保留外层结构。最终每个被修改的元素都会被输出成一个独立的JSON对象。 - 未使用
|=绑定修改到原对象:如果没有用|=把修改操作绑定到原数组或原对象上,而是直接输出修改后的片段,jq会把每个处理结果单独输出,导致多个JSON对象。
举个反例(会输出多个JSON):
# 错误写法,不要用这个 jq '.signal[] | select(.name | contains("signal")) | .nested.prop = "CHANGED-" + (.name | match("\\d$").string)' input.json
这个命令会输出两个独立的JSON对象(对应示例里的signal1和signal5),而不是完整的原JSON结构。
内容的提问来源于stack exchange,提问作者Daniel Kaplan
相关产品推荐
相关产品推荐

