I wanted to use jq to get a specific value b
from two possible paths (and these two only). So, basically, I wanted to say
jq '(path1 OR path2) | .b'
which should work if b
is at one of the two paths path1
or path2
. If both paths has b
, then the first path takes precedence.
For example, both
echo '{"b":2}' | jq '.b'
echo '{"a": {"b":2}}' | jq '.a.b'
extract b
at .
and .a
.
Can I somehow say
echo ... | jq '(MAGIC).b'
to make it work for both inputs above?
What I tried so far is to use the recursive operator ..
:
jq '[..|.b?|values]|first'
This kind of works in that both:
echo '{"b":2}' | jq '[..|.b?|values]|first'
echo '{"a": {"b":2}}' | jq '..|.b?|values|first'
give 2
. But it is not specific enough and also allows b
to be anywhere in the tree below .
. It is also difficult to read. In addition, it may not work if the two paths are not parent-children related.
(This is with jq 1.7 in Ubuntu 24.04 LTS)
Best Answer
This would extract the value of the top-level
b
key, but if that value is missing,null
, orfalse
(i.e, if the value is false in a boolean context), use theb
key undera
.The above would be short and snappy if you knew that your top-level
b
key never corresponds to a boolean value. For a more general approach, you would need to test for existence of theb
key rather than testing its value:This would extract the value of the top-level
b
key, if it exists, and would otherwise return the other key's value. This would be able to returnfalse
ornull
for the top-levelb
key if that is the value the key has.As for your "magic" expression, in the exact form that you asked for it, i.e.
(MAGIC).b
:Here, the
if
statement returns either.
or.a
depending on whether theb
key exists in the current object or not. Theb
key's value is the extracted from whichever object the "magic" expression returns.