jq - how |= operator works?

Viewed 2202

In the JQ Manual, there is an Update-assignment: |= filter and its example.

jq '(..|select(type=="boolean")) |= if . then 1 else 0 end'
Input   [true,false,[5,true,[true,[false]],false]]
Output  [1,0,[5,1,[1,[0]],0]]

Why this does not produce a JSON stream below but maintains the original nested list format?

1
0
1
1
0
0

For me, (..|select(type=="boolean")) produces:

true
false
true
true
false
false

Then applying |= if . then 1 else 0 end would not produce this?

1
0
1
1
0
0

Please help understand how **|= ** operation maintains can maintain the format of the input.

2 Answers

On the right-hand side of |=, the . doesn't refer to each Boolean value output by the left-hand side. It refers to the path to each value produced by the left-hand side.

The filter (..|select(type=="boolean")) |= if . then 1 else 0 end, given your input, is equivalent to

.[0] |= if . then 1 else 0 end | 
.[1] |= if . then 1 else 0 end |
.[2][0] |= if . then 1 else 0 end | ...

Any assignment, whether it's via =, |= or any other, does not change the context as a result of the assignment. It just updates the selected value and passes along the original . input. And as chepner points out, the expression expanded out is just a sequence of assignments, none of which changes the context.

If you wanted to get just the mapped out values, you wouldn't want to do an assignment here and just do a regular pipe.

.. | select(type=="boolean") | if . then 1 else 0 end
Related