jonseymour
jonseymour

Reputation: 1106

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

Upvotes: 2

Views: 48

Answers (1)

pmf
pmf

Reputation: 36391

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

Upvotes: 2

Related Questions