Home > Mobile >  Count number of objects whose attribute are "null" or contain "null"
Count number of objects whose attribute are "null" or contain "null"

Time:06-04

I have the following JSON. From there I'd like to count how many objects I have which type attribute is either "null" or has an array that contains the value "null". In the following example, the answer would be two. Note that the JSON could also be deeply nested.

{
  "A": {
    "type": "string"
  },
  "B": {
    "type": "null"
  },
  "C": {
    "type": [
      "null",
      "string"
    ]
  }
}

I came up with the following, but obviously this doesn't work since it misses the arrays. Any hints how to solve this?

jq '[..|select(.type?=="null")] | length'

CodePudding user response:

This answer focuses on efficiency, straightforwardness, and generality.

In brief, the following jq program produces 2 for the given example.

  def count(s): reduce s as $x (0; . 1);

  def hasValue($value):
    has("type") and 
      (.type | . == $value or (type == "array" and any(. == $value)));

  count(.. | objects | select(hasValue("null")))

Notice that using this approach, it would be easy to count the number of objects having null or "null":

count(.. | objects | select(hasValue("null") or hasValue(null)))

CodePudding user response:

You were almost there. For arrays you could use IN. I also used objects, strings and arrays which are shortcuts to a select of the according types.

jq '[.. | objects.type | select(strings == "null", IN(arrays[]; "null"))] | length'
2

Demo


On larger structures you could also improve performance by not creating that array of which you would only calculate the length, but by instead just iterating over the matching items (e.g. using reduce) and counting on the go.

jq 'reduce (.. | objects.type | select(strings == "null", IN(arrays[]; "null"))) as $_ (0; . 1)'
2

Demo

  • Related