Search code examples
selectnulljqis-empty

Unexpected action of jq select filter


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


Solution

  • 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