Как преобразовать массив JSON в карту JSON: одно конкретное значение атрибута элемента массива становится ключом каждой карты

Я хотел бы преобразовать JSON листинга процесса pm2 в Node.js (pm2 jlist > pm2-jlist.json), чтобы передать его в несколько другом формате в collectd (телеметрия).

Введите JSON:

[
    {
        "pid": 1419,
        "name": "myapp",
        "pm_id": 0,
        "monit": {
            "memory": 13795328,
            "cpu": 0
        }
    },
    {
        "pid": 1425,
        "name": "calendar-viewer",
        "pm_id": 1,
        "monit": {
            "memory": 22761472,
            "cpu": 0
        }
    }
]

Ожидаемый результат:

{
    "myapp": {
        "cpu": 0,
        "memory": 14548992,
        "pid": 1419
    },
    "calendar-viewer": {
        "cpu": 0,
        "memory": 16957440,
        "pid": 1425
    }
}

Поэтому я хочу преобразовать каждый элемент массива входного массива JSON в элемент карты JSON следующим образом:

  1. Значение атрибута с ключом name становится ключом этого элемента карты.

  2. Атрибуты поддерева "monit" объединяются под ключом этой карты (эта часть уже работает).

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

Попробуйте №1: это почти правильно, но результат содержит 2 объекта json (недопустимый синтаксис) вместо 1 объекта json ...

cat pm2-jlist.json | jq '.[] | {(.name): {pid: .pid,cpu: .monit.cpu, memory: .monit.memory}}'

{
  "myapp": {
    "pid": 1419,
    "cpu": 0,
    "memory": 14548992
  }
}
{
  "calendar-viewer": {
    "pid": 1425,
    "cpu": 0,
    "memory": 16957440
  }
}

Попробуйте №2: я могу отфильтровать только 1 объект json, но мне нужны все элементы в 1 объекте json ...

cat pm2-jlist.json | jq '.[] | select(.name == "calendar-viewer")| {(.name): {pid: .pid, cpu: .monit.cpu, memory: .monit.memory}}'

{
  "calendar-viewer": {
    "pid": 1425,
    "cpu": 0,
    "memory": 16957440
  }
}

Спасибо за ваше время.


person Rolf    schedule 08.12.2016    source источник


Ответы (2)


С вашим вводом фильтр:

map( { (.name): (.monit + {pid} ) } ) | add

производит:

{
  "myapp": {
    "memory": 13795328,
    "cpu": 0,
    "pid": 1419
  },
  "calendar-viewer": {
    "memory": 22761472,
    "cpu": 0,
    "pid": 1425
  }
}
person peak    schedule 08.12.2016
comment
Прекрасно работает. Спасибо за вашу помощь с использованием map () и добавьте - person Rolf; 08.12.2016

Я не эксперт по jq, но концептуально то, что вам нужно, это reduce.

Вот мое лучшее предположение, учитывая, как я ожидаю, что все будет работать ...

reduce .[] as $item ({}; .[$item.name] = {"cpu" : $item.monit.cpu, "memory" : $item.monit.memory, "pid" : $item.pid})

Как бы то ни было, jqplay.org производит следующий вывод для ваших входных данных и указанный выше фильтр:

{
  "myapp": {
    "cpu": 0,
    "memory": 13795328,
    "pid": 1419
  },
  "calendar-viewer": {
    "cpu": 0,
    "memory": 22761472,
    "pid": 1425
  }
}
person JonSG    schedule 08.12.2016
comment
Это прекрасно работает. Я предпочитаю ответ от ‹peak›, потому что он проще. Я думаю, что пик является (одним из) авторов jq, потому что он в основном дает лучший ответ - person Rolf; 08.12.2016