Editing config files, bumping versions and patching API payloads require changing a field without rebuilding the whole document.
Most jq filters extract. Assignment operators instead return the whole input with something changed.
.version = "2.0"sets a field (creating it if missing). The right side is evaluated against the original input, so.b = .acopies.ainto.b..price |= . * 1.1updates: the right side runs with the current value at that path as input. This is the one you want most of the time.- Arithmetic shortcuts:
.count += 1,-=,*=,/=, and//=which sets a default only if the value is null or false.
The left side can be any path expression, including iterators and select:
.items[].price |= . * 0.9discounts every item.(.items[] | select(.sku == "A1") | .qty) += 5updates only matching items..users |= map(select(.active))filters a nested list in place.
del(path) removes; to_entries-style rewrites are rarely needed.
jq never edits files in place. Write to a temporary file and move it: jq '.version = "2.0"' package.json > tmp && mv tmp package.json (or sponge from moreutils). Redirecting to the same file you read (> package.json) truncates it before jq reads it, leaving it empty.
Example
echo '{"version":"1.0","items":[{"sku":"A1","qty":1,"price":10},{"sku":"B2","qty":3,"price":20}]}' > o.json
jq -c '.version = "2.0" | .version' o.json # "2.0"
jq -c '.items[].price |= . * 0.5 | [.items[].price]' o.json # [5,10]
jq -c '(.items[] | select(.sku == "A1") | .qty) += 5 | .items[0].qty' o.json # 6
jq -c '.items |= map(select(.qty > 1)) | .items | length' o.json # 1
jq -c '.owner //= "nobody" | .owner' o.json # "nobody"
jq -c 'del(.items[] | select(.sku == "B2")) | .items' o.json
# [{"sku":"A1","qty":1,"price":10}]
jq '.version = "2.0"' o.json > o.tmp && mv o.tmp o.json # safe "in-place" editRemember
- |= updates with the value at the path as input; = uses the whole input
- Left side can use .[] and select to update many places
- Write to a temp file then mv; never > the same file
Watch out for
- Running jq ... file.json > file.json, which empties the file before jq reads it.