I need to set the value of a field in a json doc to one of three values using jq, depending on which exists. Notionally this looks like: set X to (if A exists, else if B exists, else if C exists, else "")
.
An example json doc I have looks like this:
{
"name": "0230",
"publish_date": "2007-08-18",
"abc_severity": "",
"def_severity": "medium",
"ghi_severity": "negligible"
}
I would like to create a field Severity
and set it's value to the value of abc_severity
not null or empty. if it is null or empty I would like to set it to def_severity
, and if that's null or empty I would like to set it to ghi_severity
. If all three are null or empty is may be created with an empty value ""
. So the output in this case would be:
{
"name": "0230",
"publish_date": "2007-08-18",
"abc_severity": "",
"def_severity": "medium",
"ghi_severity": "negligible",
"Severity": "medium"
}
The following is the closest I seem to be able to get:
'. | if .abc_severity? then .Severity=.abc_severity else if .def_severity? then .Severity=.def_severity else if .ghi_severity? then .Severity=.ghi_severity else .Severity="" end end end'
But the value of Severity
is always ""
even if one or more of the other values exist. I'm sure I'm overlooking something simple here, I just can't seem to get it.
Best Answer
An empty string is still a string, so
.abc_severity?
would give you an empty string, notnull
(orfalse
). Also, note that the question mark means approximately "replace withnull
if this key does not exist". In the example, all three keys exist, and their values are notnull
.If you had been using
null
for empty values, yourjq
expression would have looked likeThe above expression would have picked the first of the three values that weren't
null
, testing the left-most first and going right, ornull
if all of them werenull
. But that won't work now as we have to deal with empty strings as if they werenull
.We can do that by introducing a helper function (to reduce our typing a bit):
Our helper function
n
returns the string as-is if it is not empty; otherwise, it returnsnull
. With chained//
operators, we pick the first value of the three that is notnull
, when seen throughn
, or the empty string if all three values arenull
.Testing the above on the command line with your data: