2

I have been using jq for quite a while, but some behaviour today has surprised me:

I expected this:

 echo '{"Name":"NAME","Tags":[{"Key":"KEY","Value":"HASH"}]}' \
 | jq '{"name": .Name, "hash": (.Tags[]|select(.Key=="hash")|.Value)}'

to produce this:

{
   "name": "NAME",
   "hash": null
}

but instead, it filters out the entire object from the output completely.

As a sanity check changing the filter to a value that does match as follows::

 echo '{"Name":"NAME","Tags":[{"Key":"KEY","Value":"HASH"}]}' \
| jq '{"name": .Name, "hash": (.Tags[]|select(.Key=="KEY")|.Value)}'

produces the expected output:

{
   "name": "NAME",
   "hash": "HASH"
}

The output of the first case, select(.Key=="hash"), is surprising to me since the select filter is meant to be acting on the stream produced by .Tags[] and not the entire input stream.

How do I express what I want to express, which is if there is no matching Tag, the "hash" property of the output object should be set to null?

I am using jq 1.6 on OSX

peak
  • 105,803
  • 17
  • 152
  • 177
jonseymour
  • 1,006
  • 1
  • 12
  • 22

1 Answers1

2

If a part of a filter produces empty, it will suck in everything that is compund to it.

Solution: Don't let it produce empty. One way would be to give the select filter an alternative: select(.Key=="hash") // null

jq '{"name": .Name, "hash": (.Tags[] | select(.Key=="hash") // null | .Value)}'
{
  "name": "NAME",
  "hash": null
}

Demo

pmf
  • 24,478
  • 2
  • 22
  • 31