Как получить рекурсивный путь к определенному ключу (не отображая имя ключа родителей, но значение из другого ключа каждого родителя) - PullRequest
2 голосов
/ 03 мая 2019

У меня есть следующий JSON

[
  {
    "name": "alpha"
  },
  {
    "fields": [
      {
        "name": "beta_sub_1"
      },
      {
        "name": "beta_sub_2"
      }
    ],
    "name": "beta"
  },
  {
    "fields": [
      {
        "fields": [
          {
            "name": "gamma_sub_sub_1"
          }
        ],
        "name": "gamma_sub_1"
      }
    ],
    "name": "gamma"
  }
]

и я хотел бы получить пути "name", необходимые для получения каждого значения "name". Учитывая приведенный выше код, я хотел бы получить следующий результат:

"alpha"
"beta.beta_sub_1"
"beta.beta_sub_2"
"beta"
"gamma.gamma_sub_1.gamma_sub_sub_1"
"gamma.gamma_sub_1"
"gamma"

Я искал вокруг, но я не мог добраться до этого результата. Пока у меня есть это:

tostream as [$p,$v]   | select($p[-1] == "name" and $v != null)   | "\([$p[0,1]] | join(".")).\($v)"

но это дает мне путь с ключевым именем родителей (и не сохраняет всех родителей-посредников.

"0.name.alpha"
"1.fields.beta_sub_1"
"1.fields.beta_sub_2"
"1.name.beta"
"2.fields.gamma_sub_sub_1"
"2.fields.gamma_sub_1"
"2.name.gamma"

Есть идеи?

P.S .: Я искал очень подробный документ по jq, но не смог найти ничего хорошего. Если у кого-то есть какие-либо рекомендации, я буду признателен.

1 Ответ

0 голосов
/ 03 мая 2019

Описание проблемы не похоже на пример ввода-вывода, но следующая jq-программа выдает требуемый вывод:

def descend:
  select( type == "object" and has("name") )
  | if has("fields") then ([.name] + (.fields[] | descend)) else empty end, 
    [.name] ;

.[]
| descend
| join(".")

С вашим вводом и использованием параметра командной строки -r это выдает:

alpha
beta.beta_sub_1
beta.beta_sub_2
beta
gamma.gamma_sub_1.gamma_sub_sub_1
gamma.gamma_sub_1
gamma

Ресурсы

Помимо jq руководства , FAQ и Поваренная книга , вам может пригодиться следующее:

...