girlcode
girlcode

Reputation: 3265

How do I filter on an optional property value only if it exists?

I have JSON such as:

{ "message": "hi" }

But it can also be of the format:

{ "message": { "action": "foo" } }

I want to filter out any records where the message.action == "foo" IF message.action even exists.

If I use the command:

jq 'select(.message.action? == null or .message.action? != "foo" )'

Then I get zero results. This appears to be because once you check for action, it then filters out any messages that are not objects, but I still want to be able to display { message: "hi" }

Upvotes: 0

Views: 271

Answers (2)

chepner
chepner

Reputation: 531798

You can use the alternative operator // to provide a default value for action when it does not exist (whether because it is missing or because the value is not an object in the first place):

jq 'select((.message.action? // "foo") != "foo")'

This will accept either {"message": "hi"} or {"message": {"action": "not foo"}}, but not {"message": {"action": "foo"}}.

Upvotes: 0

oguz ismail
oguz ismail

Reputation: 50785

Check if message points to an object which has the key action whose value is foo instead, and take logical complement of the result. There's no harm in typing a few more letters.

select(.message | type == "object" and has("action") and .action == "foo" | not)

Upvotes: 2

Related Questions