How to check if a json is empty using bash or jq?

Viewed 213

I have a function that checks for duplicate values held within objects inside a json file. When duplicates are found the function returns something like this:

{
  "Basket1": [
    Apple,
    Orange
  ],
  "Basket2": [
    Apple,
    Orange
  ]
}

If no duplicates are found then it returns am empty list:

{}

Currently I am using -s in bash like such to check if the there are dups found within the output:

<"$baskets" jq -L $HOME 'check_dups' > "$dups"
  if [[ ! -s "$dups" ]];
    then
      echo -e "${RED}[Error]${NC} Duplicates found! Please review duplicates below" >&2
      echo "$(cat "$dups" | jq '.')"
    else
      echo -e "${GREEN}[SUCCESS]${NC} No duplicates found" >&2
  fi

However empty object returned if no dups are found will cause the -s file check in bash to succeed regardless. What would be the best way using jq or bash to check whether the output of this function is an empty object or not?

3 Answers

You can use error() to cause a failure if your input is identical to {}, and proceed otherwise.

jq '
  if . == {} then error("empty document found") else . end
  | ...rest of your processing here...
'

As a quick example:

<<<"{}" jq 'if . == {} then error("empty document found") else . end | {"output": (.)}'

...emits a nonzero exit status even without jq -e.


(Addressing a concern @Thomas brought up, error() has a different exit status than an input parsing error; the former is 4, the latter is 5, while compile errors are 3; so should there be a need to distinguish them it's entirely possible).

You can compare to the empty object {}, so . == {} or . != {} produce a boolean, which should do what you want.

Furthermore, you could use jq's -e option which sets the exit code based on the result, for integration into the shell:

<"$baskets" jq -L $HOME 'check_dups' > "$dups"
if jq -e '. == {}' <"$dups" >/dev/null
  then ...
  else ...
fi

You could stick with your approach using the shell's -s test by arranging for your jq command to emit nothing instead of {}. This could be done using the following at the end of your jq program:

if . == {} then empty else . end
Related