Я пытаюсь обновить файл json
, используя jq
. Мой файл json выглядит так
{
"A": "123",
"B": "456",
"C": "789",
"D": []
}
Здесь значение для ключа D
пусто, поэтому я добавляю к нему некоторые значения. И это работает
Теперь, если по какой-то причине ключ не существует, мне нужно сначала создать ключ D
. И я не могу этого добиться
{
"A": "123",
"B": "456",
"C": "789",
}
cat test.json | jq 'has("D")' = false && cat test.json jq --argjson addobj '{"D": "[]"}'
я получаю сообщение об ошибке
jq: error: Could not open file =: No such file or directory
jq: error: Could not open file false: No such file or directory
ожидаемый результат
{
"A": "123",
"B": "456",
"C": "789",
"D": []
}
Может кто-нибудь, пожалуйста, дайте мне знать, в чем проблема здесь и как ее решить?
Заранее спасибо.
P.S. Пожалуйста, дайте мне знать, если здесь отсутствует какая-либо информация.
Да, если D не существует, я хочу создать пустой массив "D:[]"
Но что, если он существует? Пожалуйста, не отвечайте только на половину вопроса в комментарии.
Ваша проблема не (только) с jq, а с синтаксисом оболочки.
Но если все, что вы пытаетесь сделать, это обновить значение ключа D независимо от того, существует оно или нет, то вам не нужны никакие проверки, и вы можете просто присвоить новое значение:
$ jq '.D = ["new value"]' test.json
{
"A": "123",
"B": "456",
"C": "789",
"D": [
"new value"
]
}
Если вы хотите изменить текущее значение, вам может помочь оператор |=
.
Альтернативной эквивалентной программой будет '. + { D: ["new value"] }'
Если вы действительно хотите исправить свой скрипт, вот его рабочая версия:
if jq -e 'has("D")' test.json >/dev/null; then
# key exists
jq --argjson addobj '{"D": "[]"}' 'your program here' test.json
else
# key doesn't exist
jq 'your other program here'
fi
Но это, возможно, проще в jq напрямую:
jq --argjson addobj '{"D": "[]"}' '
if has("D") then
# D exists
. # <- your jq program
else
# D doesn't exist
. # <- your other jq program
end
' test.json
Если ваша цель состоит в том, чтобы просто вставить ключ со значением по умолчанию, если он не существует, но сохранить любое существующее значение, следующая простая программа jq (и ничего больше) должна позаботиться об этом:
jq '{D: []} + .' test.json
(ключи справа перезаписывают ключи слева — {a:1}+{a:2}
становится {a:2}
)
Объекты в JavaScript (и в расширении JSON) представляют собой набор неупорядоченных пар ключ-значение, а {a:1,b:2}
— это тот же объект, что и {b:2,a:1}
.
Однако jq в основном сохраняет порядок ключей (хотя я не думаю, что это указано/гарантировано). Итак, немного более сложная версия, которая помещает D
в конец объекта, но сохраняет существующие значения:
jq '.D |= (. // [])' test.json
Привет @knittl, спасибо за обновление. Моя цель - условно проверить, существует ли ключ, а если нет, создать ключ. В вашем решении, что вы подразумеваете под «вашей другой программой jq» в другой части?
@Preeti, вы можете отредактировать свой вопрос, включив в него следующее: ввод с ключом, ввод без ключа, ожидаемый результат для обоих. Я не уверен, что действительно понимаю, что вы пытаетесь сделать (и зачем вам для этого нужно условие)
Я обновил вопрос. Все, что я хочу сделать, это добавить ключ, если он не существует, а позже я обновлю его значение, если он пуст.
@Preeti, моя последняя программа должна прекрасно об этом позаботиться. Всегда ли файл содержит значение, которое вы хотите вставить? Если это так, первая программа тоже будет работать (просто замените значение на любое значение, которое вам нужно). Итак, если D
существует, это всегда будет пустой массив или это может быть другое значение, которое вы хотели бы сохранить? Потому что, если это так, вы можете просто перезаписать его. Перезапись значения с тем же значением ничем не отличается от того, чтобы не перезаписывать его; конечный результат идентичен.
Я попробовал вашу последнюю программу jq '{D: []} + .' test.json
и изменил ее на cat test.json | jq 'has("D")' = false && jq '{D: []} + .' test.json
. Но это дает мне jq: error: Could not open file =: No such file or directory
@Preeti, почему ты меняешь это? Синтаксис вашей оболочки совершенно неверен (см. первый абзац ответа). Программа уже делает то, что вы просите, нет необходимости добавлять дополнительные каналы или параметры.
Но простое выполнение jq '{D: []} + .' test.json
не добавляет ключ.
@Preeti уверен, что да, я проверил это (снова). Он не изменяет файл (jq просто не может этого сделать). Чтобы изменить файл, перенаправьте вывод в новый файл, а затем переместите его поверх старого файла (или используйте губку GNU). Почти ни один инструмент Linux CLI не изменяет свои входные файлы напрямую; +99% всех инструментов потребляют файлы или стандартный ввод и записывают результат в стандартный вывод. Используйте перенаправление ввода-вывода оболочки для записи вывода в файлы (тогда это не вопрос jq)
да «Он не изменяет файл (jq просто не может этого сделать). Чтобы изменить файл, перенаправьте вывод в новый файл, а затем переместите его поверх старого файла», в этом была хитрость. Теперь это работает, за исключением того, что новый ключ добавляется вверху, а не в конце. Могу ли я сделать, чтобы добавить в конце?
Порядок ключей в JSON не имеет значения; объект представляет собой неупорядоченный набор пар ключ-значение. Но я спрошу еще раз, что я прокомментировал ниже вопрос: вы всегда хотите пустой массив? Или вы хотите сохранить непустые массивы, если они уже есть? В этом случае, возможно, есть способ обойти это.
Да, я хочу сохранить непустые массивы, если они уже есть. И в случае, если "D:[]" существует, но пуст, я добавлю к нему некоторые значения.
@Preeti смотрите обновленный ответ. Кстати, было бы очень полезно, если бы в вопросе упоминалось об этом (или вместо этого использовалось входное значение, содержащее значения, а не пустой массив).
Всегда ли это «D: []» и «D отсутствует» или это также может быть «D: [1,2]» (или любое другое значение)? Другими словами: вы всегда хотите получить пустой массив?