Reputation: 1907
In jq, how do I ensure a k,v is only created if it exists in the object being inspected? For example, let's say I have an object like:
{
"student":{
"name": "george",
"age" : "15",
"quote": "Hello I am George"
}
}
And I do cat text.txt | jq '{name: .student.name, quote: .student.quote}'
to create:
{
"name": "george",
"quote": "Hello I am George"
}
However, some of the entries are incomplete, and I don't want to write an empty K,V. Let's say I get:
{
"student":{
"name": "Shirley"
}
}
With the current jq above this would create:
{
"name": "Shirley",
"quote": null,
}
Is there a way I can tell jq to only create the 'quote'
key if it exists (i.e. is not null)? Or more generally, create ALL keys only if they exist in the object being inspected.
Upvotes: 3
Views: 7398
Reputation: 134491
If you know what the keys are ahead of time and they're straight properties, just build up an array of the keys you want and check if the object contains those keys.
$ jq --argjson keys '["name","quote"]' '
def copy_keys($keys): . as $o
| reduce $keys[] as $k ({}; if ($o|has($k)) then .[$k] = $o[$k] else . end)
;
.student | copy_keys($keys)' text.txt
But the way you worded your question, "Or more generally, create ALL fields only if they exist in the object being inspected," you just want all the keys in the object as long as it has a key. Why not just get the object?
$ jq '.student' text.txt
Upvotes: 2
Reputation: 116870
This is where object addition comes in very handy, especially since $obj + null
yields $obj
(if $obj
is a JSON object):
.student | {name} + if has("quote") then {quote} else null end
or equivalently:
def maybe(k): if has(k) then {(k): .[k]} else null end;
.student | {name} + maybe("quote")
A slightly different approach, with subtly different semantics, would be:
.student | {name} + ((select(.quote) | {quote}) // null)
Of course other variations are possible.
Upvotes: 9