Используйте jq для обновления свойства объекта, который содержит другое свойство с определенным значением.

Вопрос или проблема

С помощью jq, возможно ли обновить значение свойства объекта, которое содержит определенное значение в другом свойстве?

В примере ниже я хочу установить значение свойства “value” всех объектов, у которых “keyname” = “foo”.

Пример .json файла выглядит так:

"root" : {
  "instances": [
    {
      "name": "1",
      "configs": [
        {
          "keyname": "foo",
          "value": "" // <- обновить/установить это
        },
        {
          "keyname": "barrr",
          "value": "barrrr"
        }
      ]
    },
    {
      "name": "2",
      "configs": [
        {
          "keyname": "foo",
          "value": "" // <- обновить/установить это
        },
        {
          "keyname": "buzzz",
          "value": "buzzz"
        }
      ]
    }
  ]
}

Я попробовал это, но безуспешно, появляется ошибка о том, что массив не является строкой:

jq '(.root.instances.configs[] | select(.keyname==foo)).value = foo'

Предполагая, что ваш JSON-документ правильно сформирован, чего нет в вашем примере, так как он содержит несколько ошибок:

$ cat file
{
  "root": {
    "instances": [
      {
        "name": "1",
        "configs": [
          {
            "keyname": "foo",
            "value": ""
          },
          {
            "keyname": "barrr",
            "value": "barrrr"
          }
        ]
      },
      {
        "name": "2",
        "configs": [
          {
            "keyname": "foo",
            "value": ""
          },
          {
            "keyname": "buzzz",
            "value": "buzzz"
          }
        ]
      }
    ]
  }
}
$ jq '( .root.instances[].configs[] | select(.keyname == "foo") ).value = "foo"' file
{
  "root": {
    "instances": [
      {
        "name": "1",
        "configs": [
          {
            "keyname": "foo",
            "value": "foo"
          },
          {
            "keyname": "barrr",
            "value": "barrrr"
          }
        ]
      },
      {
        "name": "2",
        "configs": [
          {
            "keyname": "foo",
            "value": "foo"
          },
          {
            "keyname": "buzzz",
            "value": "buzzz"
          }
        ]
      }
    ]
  }
}

Это выражение jq обновляет значение ключа .value на строку foo. Обновляемый ключ выбирается из одного из элементов .root.instances[].configs[]. Обратите внимание, что .root.instances является массивом, и каждый элемент .configs в каждом из его элементов также является массивом. Оператор select() проверяет ключ .keyname со строкой foo.

Сделать ключ запроса и новое значение переменными можно следующим образом:

jq  --arg querykey 'foo' \
    --arg newval 'The train said "choo choo"' \
    '( .root.instances[].configs[] | select(.keyname == $querykey) ).value = $newval' file

Это создает две внутренние переменные jq с названиями $querykey и $newval. Их значения будут корректно кодироваться так, чтобы, например, $newval мог содержать двойные кавычки, как показано выше.

Ответ или решение

Использование утилиты jq для обновления значений свойств объектов в JSON-файле на основании определенных условий является мощной техникой в обработке данных. В данном вопросе мы рассматриваем необходимость обновления значения свойства "value" в объектах, где свойство "keyname" имеет значение "foo". Это довольно распространенный сценарий, с которым часто сталкиваются специалисты в области информационных технологий.

Решение задачи с использованием jq

Анализ JSON-структуры

Предположим, мы имеем следующий JSON:

{
  "root": {
    "instances": [
      {
        "name": "1",
        "configs": [
          {
            "keyname": "foo",
            "value": ""
          },
          {
            "keyname": "barrr",
            "value": "barrrr"
          }
        ]
      },
      {
        "name": "2",
        "configs": [
          {
            "keyname": "foo",
            "value": ""
          },
          {
            "keyname": "buzzz",
            "value": "buzzz"
          }
        ]
      }
    ]
  }
}

Обновление с применением jq

Для того чтобы обновить значение "value" для всех объектов, содержащих "keyname" равное "foo", используйте следующий jq-запрос:

jq '( .root.instances[].configs[] | select(.keyname == "foo") ).value = "foo"' файл.json

Этот запрос выполняет следующие действия:

  1. Итерация по массивам: Мы проходим через каждый объект в "instances" и затем внутри каждого — через каждый объект в "configs".
  2. Условный выбор: Функция select(.keyname == "foo") выбирает только те объекты, где ключ "keyname" равен "foo".
  3. Обновление значения: Изменяем значение "value" на "foo".

Использование переменных в jq

Для большей гибкости можно заменить жестко заданные значения на переменные. Это полезно, если вы хотите использовать разные значения без изменения основного запроса:

jq --arg querykey 'foo' --arg newval 'Новое значение' \
   '( .root.instances[].configs[] | select(.keyname == $querykey) ).value = $newval' файл.json

В этом запросе мы определяем две переменные:

  • $querykey: значение для поиска в "keyname".
  • $newval: новое значение для "value".

Заключение

Использование jq предоставляет мощные инструменты для работы с JSON-данными. Правильное применение этих инструментов требует четкого понимания структуры данных и условий задания. Приведенные примеры помогут вам успешно обновлять JSON-документы, используя эффективно написанные и адаптивные команды jq.

Пожалуйста, не забывайте проверять структуру JSON-файлов для обеспечения корректности перед выполнением операций, особенно в продакшн-средах.

Оцените материал
Добавить комментарий

Капча загружается...