Вопрос или проблема
У меня есть JSON, похожий на следующий:
Файл: my_data.json
{
"hosts": {
"1.2.3.4": { "name": "name4", "env": "test", "options": "" },
"1.2.3.5": { "name": "name5", "env": "prod", "options": "opt1,opt2" },
"1.2.3.6": { "name": "name6", "env": "qa", "options": "" },
"1.2.3.7": { "name": "name7", "env": "staging", "options": "opt3,opt4" },
"1.2.3.8": { "name": "name8", "env": "dev", "options": "opt5" },
"1.2.3.9": { "name": "name9", "env": "prod", "options": "opt6,opt7" }
}
}
Я хочу извлечь из этого CSV-файл, я пробовал несколько вариантов, которые нашел в Google, но ни один не сработал. Моя цель – получить что-то похожее на следующее:
"1.2.3.4","name4","test",""
"1.2.3.5","name5","prod","opt1,opt2"
"1.2.3.6","name6","dev",""
"1.2.3.7","name7","staging","opt3,opt4"
"1.2.3.8","name8","dev","opt5"
"1.2.3.9","name9","prod","opt6,opt7"
Я получил следующее, но не могу обратиться к ключу и не нахожу способ, чтобы это сделать.
jq --raw-output '.hosts[] | [.name, .env, .options] | @csv' my_data.json
Вот мой результат, но, как видно, он неполный. Как мне добавить ключ к каждому объекту?
"name4","test",""
"name5","prod","opt1,opt2"
"name6","qa",""
"name7","staging","opt3,opt4"
"name8","dev","opt5"
"name9","prod","opt6,opt7"
Я сделал это:
jq --raw-output '.hosts | keys_unsorted[] | [.] | @csv' my_data.json
Но это только извлекает ключи, и я не нашел способ обратиться к объекту, используя ключ.
"1.2.3.4"
"1.2.3.5"
"1.2.3.6"
"1.2.3.7"
"1.2.3.8"
"1.2.3.9"
Я мог бы попробовать объединить обе таблицы, но это может привести к ошибкам, и я знаю, что должен быть способ сделать это в jq, но я просто не могу найти метод.
Я провел несколько поисков в Google и нашел один многообещающий, но он не работает:
jq --raw-output '.hosts | keys_unsorted[] as $k | [$k, \(.[$k] | .name), \(.[$k] | .env), \(.[$k] | .options)] | @csv' my_data.json
Этот вызов возвращает ошибки компиляции:
jq: error: syntax error, unexpected INVALID_CHARACTER (Unix shell quoting issues?) at <top-level>, line 1:
.hosts | keys_unsorted[] as $k | [$k, \(.[$k] | .name), \(.[$k] | .env), \(.[$k] | .options)] | @csv
jq: error: syntax error, unexpected ')', expecting $end (Unix shell quoting issues?) at <top-level>, line 1:
.hosts | keys_unsorted[] as $k | [$k, \(.[$k] | .name), \(.[$k] | .env), \(.[$k] | .options)] | @csv
jq: 2 compile errors
Используйте keys_unsorted
или to_entries
, чтобы получить доступ к ключам:
.hosts | keys_unsorted[] as $key
| [$key, (.[$key] | .name, .env, .options)] | @csv
или
.hosts | to_entries[]
| [.key, (.value | .name, .env, .options)] | @csv
"1.2.3.4","name4","test",""
"1.2.3.5","name5","prod","opt1,opt2"
"1.2.3.6","name6","qa",""
"1.2.3.7","name7","staging","opt3,opt4"
"1.2.3.8","name8","dev","opt5"
"1.2.3.9","name9","prod","opt6,opt7"
После экспериментов с jqkungfu.com я нашел решение:
jq --raw-output '.hosts | keys_unsorted[] as $k | [$k, .[$k].name, .[$k].env, .[$k].options] | @csv' my_data.json
Это вернет желаемый вывод:
"1.2.3.4","name4","test",""
"1.2.3.5","name5","prod","opt1,opt2"
"1.2.3.6","name6","qa",""
"1.2.3.7","name7","staging","opt3,opt4"
"1.2.3.8","name8","dev","opt5"
"1.2.3.9","name9","prod","opt6,opt7"
Ответ или решение
Как использовать jq
для извлечения JSON в CSV: Пошаговое руководство
Если вы работаете с JSON-файлами и хотите извлечь данные в формате CSV, jq
— это мощный инструмент, который может вам помочь. В этом руководстве мы рассмотрим, как извлечь значения ключей и их внутренние значения из JSON-структуры, используя jq
.
Исходные данные
Предположим, у нас есть JSON-файл my_data.json
, содержащий следующую структуру:
{
"hosts": {
"1.2.3.4": { "name": "name4", "env": "test", "options": "" },
"1.2.3.5": { "name": "name5", "env": "prod", "options": "opt1,opt2" },
"1.2.3.6": { "name": "name6", "env": "qa", "options": "" },
"1.2.3.7": { "name": "name7", "env": "staging", "options": "opt3,opt4" },
"1.2.3.8": { "name": "name8", "env": "dev", "options": "opt5" },
"1.2.3.9": { "name": "name9", "env": "prod", "options": "opt6,opt7" }
}
}
Наша цель — извлечь эти данные в формате CSV, чтобы результат выглядел следующим образом:
"1.2.3.4","name4","test",""
"1.2.3.5","name5","prod","opt1,opt2"
"1.2.3.6","name6","qa",""
"1.2.3.7","name7","staging","opt3,opt4"
"1.2.3.8","name8","dev","opt5"
"1.2.3.9","name9","prod","opt6,opt7"
Решение
Для достижения этой цели мы воспользуемся следующей командой jq
:
jq --raw-output '.hosts | keys_unsorted[] as $k | [$k, .[$k].name, .[$k].env, .[$k].options] | @csv' my_data.json
Разберем по шагам, как работает эта команда.
-
--raw-output
: Этот флаг обеспечивает вывод в текстовом формате без дополнительных кавычек, что полезно для создания CSV. -
'.hosts'
: Мы начинаем с корневого узла JSON и переходим к объектуhosts
. -
keys_unsorted[] as $k
: Эта часть извлекает все ключи в объектеhosts
(в данном случае это IP-адреса) и сохраняет их в переменной$k
. -
[$k, .[$k].name, .[$k].env, .[$k].options]
: Создаем массив, который включает ключ$k
, а также значенияname
,env
иoptions
, соответствующие этому ключу. -
@csv
: Форматируем массив в виде строки CSV.
Примеры использования
После запуска команды вы должны получить желаемый вывод, который будет выглядеть следующим образом:
"1.2.3.4","name4","test",""
"1.2.3.5","name5","prod","opt1,opt2"
"1.2.3.6","name6","qa",""
"1.2.3.7","name7","staging","opt3,opt4"
"1.2.3.8","name8","dev","opt5"
"1.2.3.9","name9","prod","opt6,opt7"
Заключение
Использование jq
для извлечения данных из JSON-файлов в формате CSV открывает широкие возможности для обработки и анализа данных. Приведенная команда является универсальным решением, которое можно адаптировать под собственные нужды, изменяя структуру JSON или формат вывода. Воспользуйтесь этой возможностью, чтобы эффективно справляться со своими данными и извлекать из них максимальную пользу.