Подсчет элементов во вложенном JSON с помощью jq

#json #jq

#json #jq

Вопрос:

Я пытаюсь подсчитать все элементы во вложенном JSON-документе с jq помощью ?

Учитывая следующий JSON-документ

 {"a": true, "b": [1, 2], "c": {"a": {"aa":1, "bb": 2}, "b": "blue"}}  

Я хочу рассчитать результат 6 .

Для того, чтобы сделать это, я попробовал следующее:

 echo '{"a": true, "b": [1, 2], "c": {"a": {"aa":1, "bb": 2}, "b": "blue"}}'  | jq 'reduce (.. | if (type == "object" or type == "array")   then length else 0 end) as $counts   (1; .   $counts)'  # Actual output: 10 # Desired output: 6  

Однако это также учитывает встречающиеся объекты и массивы и, следовательно, дает 10 противоположный желаемому результат: 6

Итак, как я могу считать только элементы/конечные узлы документа?

Заранее благодарю вас за помощь!

Правка: Каков был бы эффективный подход к подсчету пустых массивов и объектов?

Комментарии:

1. Пожалуйста, покажите пример желаемого результата. Какие шесть элементов в вашем примере ввода вы хотите выделить?

2. Я прояснил это, отредактировав вопрос. Я хочу подсчитать все конечные узлы и получить одно десятичное представление общего количества.

Ответ №1:

Вы можете использовать scalars фильтр для поиска конечных узлов. Скаляры-это все «простые» значения JSON, т. Е. null , true , false , числа и строки. В качестве альтернативы вы можете сравнить type каждый элемент и использовать length его для определения того, есть ли у объекта или массива дочерние элементы.

Я немного расширил ваши входные данные, чтобы выделить еще несколько угловых случаев:

Ввод:

 {  "a": true,  "b": [1, 2],  "c": {  "a": {  "aa": 1,  "bb": 2  },  "b": "blue"  },  "d": [],  "e": [[], []],  "f": {}  }  

Это имеет 15 объектов JSON:

  • 5 из них являются массивами или объектами с детьми.
  • 4 из них являются пустыми массивами или объектами.
  • 6 из них являются скалярами.

В зависимости от того, что вы пытаетесь сделать, вы можете рассматривать только скаляры как «конечные узлы», или вы можете рассматривать как скаляры, так и пустые массивы и объекты как конечные узлы.

Вот фильтр, который подсчитывает скаляры:

 [..|scalars]|length  

Выход:

 6  

И вот фильтр, который подсчитывает все сущности, у которых нет потомков. Он просто явно проверяет все скалярные типы (для значения JSON существует только шесть возможных типов), и если это не один из них, это должен быть массив или объект, где мы можем проверить, сколько у него дочерних length элементов .

 [  ..|  select(  (type|IN("boolean","number","string","null")) or  length==0  ) ]| length  

Выход:

 10  

Комментарии:

1. Отлично, спасибо вам! Каков был бы эффективный подход к подсчету пустых массивов и объектов?

2. Большое спасибо за добавление объяснения и решения для подсчета пустых объектов. Ваша статья с подробным описанием внутренней работы очень ценится.