Как получить ключи и ключевые типы вложенных JSON с помощью JQ - PullRequest
0 голосов
/ 22 декабря 2019

У меня есть файл data.json, как показано ниже -

     { 
       "parameter": {
        "colA": "No",
        "COLB": "No"
      },
      "workRequired": 0,
      "work": 0,
      "updateType": "AUTO"
}

Я знаю, как получить ключ и тип ключа json -

jq -c 'to_entries[] | [.key, (.value|type)]' data.json

, но приведенная выше команда возвращает меня-

["parmeter","object"]
["workRequired","string"]
["work","null"]
["updateType","number"]

, но я хочу, чтобы команда возвращалась, как показано ниже, чтобы я получал тип ключа вложенного json -

["parmeter"."colA","string"]
["parmeter"."colB","string"]
["workRequired","string"]
["work","null"]
["updateType","number"]

Есть ли способ сделать с помощью jq

1 Ответ

2 голосов
/ 22 декабря 2019

Это очень близко к запрошенному выводу.

jq -c 'to_entries[] 
       | if .value|type == "object"
         then .key as $k 
            | .value
            | to_entries[]
            | ["\($k).\(.key)", (.value|type)]
         else [.key, (.value|type)]
         end'

Вывод:

["parameter.colA","string"]
["parameter.COLB","string"]
["workRequired","number"]
["work","number"]
["updateType","string"]

Основное различие заключается в первых двух строках. Я не думаю, что ["parameter"."colA","string'] является действительным JSON.

Некоторые типы также отличаются.

Пояснение

Один из способовизучение того, как это работает, должно идти шаг за шагом. Поэтому начните с jq -c 'to_entries[]', чтобы увидеть, что получится, а затем добавляйте каждый шаг по очереди. Руководство также довольно хорошо.

Здесь мы начнем с объекта. Первая команда - to_entries[]. Цитируя руководство, когда «to_entries передается объект, то для каждой записи k: v во входном файле выходной массив включает в себя {« key »: k,« value »: v}». Добавление [] в конце означает, что на выходе будут только объекты в массиве, которые создает to_entries. Итак, это вывод после первого шага:

{"key":"parameter","value":{"colA":"No","COLB":"No"}}
{"key":"workRequired","value":0}
{"key":"work","value":0}
{"key":"updateType","value":"AUTO"}

Теперь у нас есть четыре объекта. Один содержит другой объект. Первоначальный вопрос касается объекта, который содержит объект. Проблема заключалась в том, чтобы объединить ключ для содержащего объекта с ключом для содержащегося объекта в конечном выводе.

Условное if .value|type == "object" идентифицирует объект, содержащий объект.

Когда этоЕсли условие выполнено, .key as $k сохраняет значение ключа «key» объекта-объекта как переменную с именем $ k.

Затем мы повторяем to_entries[] с содержащимся объектом. Содержащийся объект - это значение ключа «значение» в содержащем объекте. Код .value | to_entries[] фильтрует содержащийся объект через to_entries[]. Это дает нам эти два объекта.

{"key":"colA","value":"No"}
{"key":"COLB","value":"No"}

Чтобы создать желаемый результат, нам нужно создать массив, который объединяет ключ содержащего объекта, который был сохранен как $ k, с элементами этих двухобъекты. Вот как мы это делаем. (См. «Интерполяция строк» ​​в руководстве для объяснения того, как работает часть в кавычках.)

["\($k).\(.key)", (.value|type)]

Для каждого объекта ключ, который мы сохранили как переменную $ k, имеет видв сочетании со значением ключа «ключ» в объекте. Затем мы выводим тип значения ключа «значение» в объекте.

Это дает первые две строки окончательного результата:

["parameter.colA","string"]
["parameter.COLB","string"]

Теперь мы переходим к другомуветка наша условная. Это касается трех объектов первого этапа, которые не содержат объектов. Здесь мы просто повторяем исходный код вопроса, поскольку он был удовлетворительным.

else [.key, (.value|type)]

Это дает следующее:

["workRequired","number"]
["work","number"]
["updateType","string"]

Команда end завершает условное выражение.

Еще одна вещь. Флаг -c в самом начале говорит jq, что мы хотим компактный вывод. Без него выходные данные были бы логически одинаковыми, но распределенными по нескольким строкам.

...