Closed netei closed 8 years ago
In response to the question @netei:
What do you think?
I'd say it makes sense to look at the manual, which has this to say about .foo?
:
Just like .foo, but does not output even an error when . is not an array or an object.
It's worth understanding the important role that empty
and backtracking play in jq. Meanwhile, to test whether the input is an object with a key, there are a couple of alternatives: the pedestrian way would be to test if it's an object (using type
) and whether it has a key (using has
). An alternative using ?
would be based on [ .foo? ]
because [empty]
evaluates to []
. Chances are, though, that you don't really need to perform such a test; that is, chances are that you can accomplish your actual task using backtracking.
As a workaround, you can use the alternative operator:
echo '[]' | jq 'if .key? // null == null then "" else "" end + "bar"'
As with your stated desired behaviour, this has the disadvantage of making it impossible to tell apart {"key": null}
and {}
. A better approach would be to collect .key?
on a list and compare it to the empty list:
echo '[]' | jq 'if [.key?] == [] then "" else "" end + "bar"'
And how would you delete a key only if it exists ?
I'm doing del(.msg,.requestId)
but this won't work if the input is an array , for example :
echo '[]' | jq 'del(.msg,.requestId)'
fails with jq: error (at <stdin>:1): Cannot index array with string "msg"
Should I use del(.msg?,.requestId?)
in that case ?
And how would you delete a key only if it exists ?
del(.a?)
will work as you suggest, but that's just a bit of jq magic. As far as the specification of intended behavior is concerned, it's important to distinguish the two questions:
(1) is the operation defined on a particular type? (2) does the object have the specified key?
Consider:
$ jq -nc '{"a":1,"b":2} | del(.a)'
{"b":2}
$ jq -nc '{"a":1,"b":2} | del(.c)'
{"a":1,"b": 2}
$ jq -n '[] | if type == "object" then del(.c) else . end'
[]
@netei The ?
operator basically catches any errors and executes empty
instead.
If you want to make sure that an object has a value for some key, even if it is null
, you have to use has()
.
There's an open issue, IIRC, to add a !
operator to make it easier to express that some key must have a value, and so on.
echo '[]' | jq 'if .key? == null then "" else "" end + "bar"'
Output:
<nothing>
Expected output :"bar"
I know my input is an array and not an object, and with an object, the following code works correctly.
However, I think it would make sense that
.key?
doesn't magically stops the execution of the whole line.What do you think ?