Home > OS >  Replace null values from a select command in jq with the value of another field
Replace null values from a select command in jq with the value of another field

Time:02-11

Goal is to search for null values of part_description and insert in part field value.

[
  {
    "part": "brake-01982",
    "part_description": null,
  }
]

Expected Output

[
  {
    "part": "brake-01982",
    "part_description": "brake-01982",
  }
]

Command: jq '(.[] | select(.part_description==null).part_description) |= .part'

Results in no change

What does work is if I try to insert a string value. The double quoted string results in what I would expect. Demo below. How do I pass another fields value into this command vs a quoted string?

Command: jq '(.[] | select(.part_description==null).part_description) |= "test"'

Demo

Output

[
  {
    "part": "brake-01982",
    "part_description": "test"
  }
]

CodePudding user response:

The alternative operator // retains the first value, unless it is null, false, or empty (i.e. missing), in which case it takes on the second. Combined with the update operator |=, this can be contracted to //=.

jq '.[] |= (.part_description //= .part)'
[
  {
    "part": "brake-01982",
    "part_description": "brake-01982"
  }
]

Demo


Edit: To strictly update only in the case of null, i.e. to keep a value of false, and to not create the field if it's missing, the filter needs to check explicity for null:

jq '.[] |= ((select(has("part_description")).part_description | select(. == null)) = .part)'
[
  {
    "part": "brake-01982",
    "part_description": "brake-01982"
  }
]

Demo

CodePudding user response:

Goal is to search for null values of part_description ....

If this is indeed the goal, then you would need to test for null rather than relying on // or //=. So you could write:

map( if has("part_description") and .part_description == null
     then .part_description = .part else . end )
  • Related