Jq итерация объектов массива для создания новых объектов JSON - PullRequest
0 голосов
/ 09 мая 2018

Я долго думал и искал, но я не понял, что я ищу. Я использую JQ для анализа вывода tshark (-ek) json, но я являюсь jq newby Когда кадр является многозначным, у меня есть JSON, подобный этому:

 {
      "timestamp": "1525627021656",
      "layers": {
        "frame_time_epoch": [
          "1525627021.656417000"
        ],
        "ip_src": [
          "10.10.10.10"
        ],
        "ip_src_host": [
          "test"
        ],
        "ip_dst": [
          "10.10.10.11"
        ],
        "ip_dst_host": [
          "dest_test"
        ],
        "diameter_Event-Timestamp": [
          "May  6, 2018 19:17:02.000000000 CEST",
          "May  6, 2018 19:17:02.000000000 CEST"
        ],
        "diameter_Origin-Host": [
          "TESTHOST",
          "TESTHOST"
        ],
        "diameter_Destination-Host": [
          "DESTHOST",
          "DESTHOST"
        ],
        "diameter_CC-Request-Type": [
          "2",
          "2"
        ],
        "diameter_CC-Request-Number": [
          "10",
          "3"
        ],
        "diameter_Rating-Group": [
          "9004",
          "9001"
        ],
        "diameter_Called-Station-Id": [
          "testing",
          "testing"
        ],
        "diameter_User-Name": [
          "testuser",
          "testuser"
        ],
        "diameter_Subscription-Id-Data": [
          "66666666666",
          "77777777777"
        ],
        "gtp_qos_version": [
          "0x00000008",
          "0x00000005"
        ],
        "gtp_qos_max_dl": [
          "8640",
          "42"
        ],
        "diameter_Session-Id": [
          "test1;sessionID1;test1",
          "test2;sessionID2;test2"
        ]
      }
    }

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

{
    "frame_time_epoch": [
      "1525627021.656417000"
    ],
    "ip_src": [
      "10.10.10.10"
    ],
    "ip_src_host": [
      "test"
    ],
    "ip_dst": [
      "10.10.10.11"
    ],
    "ip_dst_host": [
      "dest_test"
    ],
    "diameter_Event-Timestamp": [
      "May  6, 2018 19:17:02.000000000 CEST"
    ],
    "diameter_Origin-Host": [
      "TESTHOST"
    ],
    "diameter_Destination-Host": [
      "DESTHOST"
    ],
    "diameter_CC-Request-Type": [
      "2"
    ],
    "diameter_CC-Request-Number": [
      "3"
    ],
    "diameter_Rating-Group": [
      "9001"
    ],
    "diameter_Called-Station-Id": [
      "testing"
    ],
    "diameter_User-Name": [
      "testuser"
    ],
    "diameter_Subscription-Id-Data": [
      "77777777777"
    ],
    "gtp_qos_version": [
      "0x00000005"
    ],
    "gtp_qos_max_dl": [
      "42"
    ],
    "diameter_Session-Id": [
      "test2;sessionID2;test2"
    ]
  }
 {
    "frame_time_epoch": [
      "1525627021.656417000"
    ],
    "ip_src": [
      "10.10.10.10"
    ],
    "ip_src_host": [
      "test"
    ],
    "ip_dst": [
      "10.10.10.11"
    ],
    "ip_dst_host": [
      "dest_test"
    ],
    "diameter_Event-Timestamp": [
      "May  6, 2018 19:17:02.000000000 CEST"
    ],
    "diameter_Origin-Host": [
      "TESTHOST"
    ],
    "diameter_Destination-Host": [
      "DESTHOST"
    ],
    "diameter_CC-Request-Type": [
      "2"
    ],
    "diameter_CC-Request-Number": [
      "10"
    ],
    "diameter_Rating-Group": [
      "9004"
    ],
    "diameter_Called-Station-Id": [
      "testing"
    ],
    "diameter_User-Name": [
      "testuser"
    ],
    "diameter_Subscription-Id-Data": [
      "66666666666"
    ],
    "gtp_qos_version": [
      "0x00000008"
    ],
    "gtp_qos_max_dl": [
      "8640"
    ],
    "diameter_Session-Id": [
      "test1;sessionID1;test1"
    ]
  }

Другой пример ручной работы: ВХОД:

{
    "key_single": ["single_value"],
    "key2": ["single_value"],
    "multiple_value_key": ["value1" , "value2"],
    "any_key_name": ["value4" ,"value5"]
}
{
    "key_single": ["single_value"],
    "key2": ["single_value"],
    "multiple_value_key": ["value6" , "value7", "value8"],
    "any_key_name": ["value9" ,"value10" , "value11"]
}

Желаемый вывод:

{
    "key_single": ["single_value"],
    "key2": ["single_value"],
    "multiple_value_key": ["value1"],
    "any_key_name": ["value4"],
}
{
    "key_single": ["single_value"],
    "key2": ["single_value"],
    "multiple_value_key": ["value2"],
    "any_key_name": ["value5"],
}
{
    "key_single": ["single_value"],
    "key2": ["single_value"],
    "multiple_value_key": ["value6"],
    "any_key_name": ["value9"],
}
{
    "key_single": ["single_value"],
    "key2": ["single_value"],
    "multiple_value_key": ["value7"],
    "any_key_name": ["value10"],
}
{
    "key_single": ["single_value"],
    "key2": ["single_value"],
    "multiple_value_key": ["value8"],
    "any_key_name": ["value11"],
}

Не могли бы вы мне помочь?

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 12 мая 2018

Вот простое решение проблемы, как описано в «комментариях», хотя выход немного отличается от показанного в Q.

Для ясности определена вспомогательная функция для создания $ i-го среза объекта, то есть для всех ключей массива с длиной массива больше 1, значение заменяется на $ i-й элемент в массиве.

def slice($i):
    map_values(if (type == "array" and length>1)
               then [.[$i]]
               else . end);

Решение тогда просто:

.layers
| range(0;  [.[] | length] | max) as $i
| slice($i)

выход

{
  "frame_time_epoch": [
    "1525627021.656417000"
  ],
  "ip_src": [
    "10.10.10.10"
  ],
  "ip_src_host": [
    "test"
  ],
  "ip_dst": [
    "10.10.10.11"
  ],
  "ip_dst_host": [
    "dest_test"
  ],
  "diameter_Event-Timestamp": [
    "May  6, 2018 19:17:02.000000000 CEST"
  ],
  "diameter_Origin-Host": [
    "TESTHOST"
  ],
  "diameter_Destination-Host": [
    "DESTHOST"
  ],
  "diameter_CC-Request-Type": [
    "2"
  ],
  "diameter_CC-Request-Number": [
    "10"
  ],
  "diameter_Rating-Group": [
    "9004"
  ],
  "diameter_Called-Station-Id": [
    "testing"
  ],
  "diameter_User-Name": [
    "testuser"
  ],
  "diameter_Subscription-Id-Data": [
    "66666666666"
  ],
  "gtp_qos_version": [
    "0x00000008"
  ],
  "gtp_qos_max_dl": [
    "8640"
  ],
  "diameter_Session-Id": [
    "test1;sessionID1;test1"
  ]
}
{
  "frame_time_epoch": [
    "1525627021.656417000"
  ],
  "ip_src": [
    "10.10.10.10"
  ],
  "ip_src_host": [
    "test"
  ],
  "ip_dst": [
    "10.10.10.11"
  ],
  "ip_dst_host": [
    "dest_test"
  ],
  "diameter_Event-Timestamp": [
    "May  6, 2018 19:17:02.000000000 CEST"
  ],
  "diameter_Origin-Host": [
    "TESTHOST"
  ],
  "diameter_Destination-Host": [
    "DESTHOST"
  ],
  "diameter_CC-Request-Type": [
    "2"
  ],
  "diameter_CC-Request-Number": [
    "3"
  ],
  "diameter_Rating-Group": [
    "9001"
  ],
  "diameter_Called-Station-Id": [
    "testing"
  ],
  "diameter_User-Name": [
    "testuser"
  ],
  "diameter_Subscription-Id-Data": [
    "77777777777"
  ],
  "gtp_qos_version": [
    "0x00000005"
  ],
  "gtp_qos_max_dl": [
    "42"
  ],
  "diameter_Session-Id": [
    "test2;sessionID2;test2"
  ]
}
0 голосов
/ 09 мая 2018

Похоже, вы хотите взять, в свою очередь, i-й элемент выбранных массивов. Используя ваш второй пример, это можно сделать так:

range(0; .multiple_value_key|length) as $i
| . + { multiple_value_key: [.multiple_value_key[$i]],
        any_key_name:       [.any_key_name[$i]] }

Выход в компактном виде:

{"key_single":["single_value"],"key2":["single_value"],"multiple_value_key":["value1"],"any_key_name":["value4"]}
{"key_single":["single_value"],"key2":["single_value"],"multiple_value_key":["value2"],"any_key_name":["value5"]}
{"key_single":["single_value"],"key2":["single_value"],"multiple_value_key":["value6"],"any_key_name":["value9"]}
{"key_single":["single_value"],"key2":["single_value"],"multiple_value_key":["value7"],"any_key_name":["value10"]}
{"key_single":["single_value"],"key2":["single_value"],"multiple_value_key":["value8"],"any_key_name":["value11"]}
...