Преобразование плоской JSON во вложенную JSON группировку по именам общих ключей - PullRequest
3 голосов
/ 06 января 2020

Я использовал JQPlay для воспроизведения формата. Я не могу понять, как использовать редуцирование по группам по дочерней структуре. Я хочу группировать на основе орг или идентификатор родителя.

просто обновил мой фильтр jqplay, но не смог удалить два тега для группировки по идентификатору.

jq play синтаксис-

Я использую приведенный ниже синтаксис в jqplay.org. Также вы можете посоветовать, пожалуйста, как отлаживать что-либо после символа трубы.

.items | {"org" : map( {id : .org, orgProperties : [{"properties" : {"methodId" : [{"id" : .methodId}]}}]})| group_by(.id) | map( reduce .[] as $x (.[0]|{}; .orgProperties+= ($x | .orgProperties)))}

Вход JSON

{
  "items": [
    {
      "org": "750141",
      "methodId": "1-10F7IAK7"
    },
    {
      "org": "750141",
      "methodId": "1-10TP18L0"
    },
    {
      "org": "750142",
      "methodId": "1-10TP18L1"
    }
  ]
}

Выход JSON

{
  "org": [
    {
      "orgProperties": [
        {
          "properties": {
            "methodId": [
              {
                "id": "1-10F7IAK7"
              }
            ]
          }
        },
        {
          "properties": {
            "methodId": [
              {
                "id": "1-10TP18L0"
              }
            ]
          }
        }
      ]
    },
    {
      "orgProperties": [
        {
          "properties": {
            "methodId": [
              {
                "id": "1-10TP18L1"
              }
            ]
          }
        }
      ]
    }
  ]
}

Ожидаемый JSON Вывод

{
  "org": [
    {
      "id": "750141",
      "orgProperties": [
        {
          "properties": {
            "methodId": [
              {
                "id": "1-10F7IAK7"
              },
              {
                "id": "1-10TP18L0"
              }
            ]
          }
        }
      ]
    },
        {
      "id": "750142",
      "orgProperties": [
        {
          "properties": {
            "methodId": [
              {
                "id": "1-10TP18L1"
              }
            ]
          }
        }
      ]
    }
  ]
} 

1 Ответ

2 голосов
/ 06 января 2020

Вам нужно сделать что-то вроде ниже. Вам нужно group_by(), а затем выполнить обработку

jq '.items | {org: group_by(.org) | map({id: .[0].org, orgProperties: [{properties: { methodId: map({id: .methodId}) }}]})} ' input.json

. Я не думаю, что существует способ повысить уровень подробного отладочного файла, выданный на jq, если только вы, возможно, не повозитесь с кодом, чтобы добавить свой код. собственные операторы отладки и запуск пользовательской сборки.

Я лично собираю фильтр из одного компонента за раз, наблюдаю за его выводом и манипулирую другими вещами. Чтобы сломать функциональность выше

  • JSON полностью реконструируется после части '.items | {org: .. фильтра. Результат следующей части формирует то, что сейчас находится под верхним уровнем "org", сечение ожидаемого вывода.
  • Как только вы выполните group_by(.org), вы получите результат, который имеет две записи массива, одна с двумя объектами (id 750141) и другой с одним объектом (id 750142).
  • Затем вы запускаете код внутри map(..) для списка объектов, возвращенного с предыдущего шага
  • Нам нужно только уникальное имя ключа в конечном результате, поэтому мы просто используем .[0].org в первом массиве. Это будет работать, даже если у вас есть несколько повторяющихся имен ключей. Сделайте паузу и посмотрите на вывод до этой точки

    {
      "org": [
        {
          "id": "750141"
        },
        {
          "id": "750142"
        }
      ]
    }
    
  • Теперь создайте остальную часть вывода с помощью orgProperties: [{properties: { methodId: ..., который создает подузлы как

    "orgProperties": [
    {
        "properties": {
            "methodId": 
    
  • Создайте конечный подмассив с помощью map({id: .methodId}), чтобы создать пару значений ключа со списком идентификаторов

...