Json извлекает список имен полей для ключа - PullRequest
0 голосов
/ 04 декабря 2018

JQ отличный инструмент.Если у меня есть файл json, я могу извлечь список ключей

примерно так:

jq keys filename | tr -d '][",'

например:

$jq  keys pipeline/components/devsvr.json  | tr -d '][",'
server1
server2

Теперь я хотел бы повторитьнад каждым ключом, перечисляя только имена полей верхнего уровня (я пытаюсь написать очень простой валидатор для некоторых json-файлов CloudFormation).

Оболочка проста - просто цикл for, но я могуне понять, как сказать jq: «покажи мне все имена полей только для ключа x.

Я тогда (в оболочке) проверим, присутствует ли каждое требуемое поле.jq сообщит с ошибкой, если json деформирован, что также полезно.

Вот пример файла:

{
  "server1": {
    "type": "single-instance",
    "stage": "10default",
    "descriptor": {
      "Resources": {
        "Instance": {
          "Properties": {
            "InstanceType": "t2.medium",
            "ImageId": {
              }
            }
          },
          "Metadata": {
            "AWS::CloudFormation::Init": {
              "app": {
                "packages": {
                  "yum": {
                    "tmux": [],
                    "vim": []
                  }
                },
                "files": {
                "sources": {},
                "commands": {},
                "services": {}
              }
            }
          }
        }
      }
    }
  },
  "server2": {
    "type": "single-instance",
    "stage": "10default",
    "descriptor": {
      "Resources": {
        "Instance": {
          "Properties": {
            "InstanceType": "t2.medium",
            "ImageId": {
              }
            }
          },
          "Metadata": {
            "AWS::CloudFormation::Init": {
              "app": {
                "packages": {
                  "yum": {
                    "tmux": [],
                    "vim": []
                  }
                },
                "files": {
                "sources": {},
                "commands": {},
                "services": {}
              }
            }
          }
        }
      }
    }
  }
}

Так что в приведенном выше примере я бы запустил ключи jqчтобы получить список ключей, а затем повторить это. Возможно, я ответил на свой вопрос с примером sed, с которым я прокомментировал, но это немного хит-робинсон, IMO. Вот результат:

$jq  '.server1' /tmp/afile   | sed -n 's#^  \"\([^"]*\).*$#\1#p'
type
stage
descriptor

(это было бы в цикле вокруг вывода команды jq 'keys').

Обновление: согласно @peak aи @ Аарон, я могу сделать это:

jq -r '. as $in | keys[] | . as $serverName | $in[$serverName] | keys | join(",") | "\($serverName) : \(.)"' pipeline/components/devsvr.json
devsvr : descriptor,stage,type
devsvr1 :

с условием, что http://json -schema.org существует для более строгой реализации.

1 Ответ

0 голосов
/ 04 декабря 2018

... используя как можно меньший набор инструментов.

Что касается обработки JSON, кажется, вам не нужно смотреть дальше jq.

Например, ваша первая команда может быть упрощена до:

jq -r 'keys[]' devsvr.json

Используйте keys_unsorted, если вы хотите, чтобы ключи были в исходном порядке.

Что еще более важно, перебирать ключи можно (и, вероятно, должно быть) сделано в JQ.Я не уверен, каковы ваши точные требования, но вы легко сможете адаптировать следующее:

jq -r '.[] | keys_unsorted[]' devsvr.json

, который производит:

type
stage
descriptor
type
stage
descriptor

Обновление

InВ соответствии с обновлением до Q следует учитывать следующий фильтр:

 keys[] as $serverName 
 | .[$serverName] 
 | "\($serverName) : \(keys|join(","))"
...