Добро пожаловать в StackOverflow!
Полный пример не был допустимым JSON объектом, и не предпринимались попытки решить проблему или пример того, как должен выглядеть желаемый результат. Таким образом, следующий ответ приходит с небольшим количеством догадок. Вероятно, это значительно увеличило бы шансы на получение хорошего ответа, если бы пример был урезан до минимального воспроизводимого примера , в котором удален весь беспорядок.
Например, "TargetAgent": "sqlrptvmjhbpr01"
представляется неактуальной информацией. Единственный эффект, который дает эта строка, состоит в том, чтобы увеличить когнитивную нагрузку на читателя при попытке расшифровки, если она имеет отношение к проблемной задаче, которой, по-видимому, нет.
Может быть ноль или много объекты DualEndPoint или Local на файл.
Вы не можете точно сказать, что такое объект DualEndPoint
или Local
.
Поскольку текст DualEndPoint
встречается только в контекст
"Type": "ConnectionProfile:FileTransfer:DualEndPoint"
Я предполагаю, что объект DualEndPoint
- это объект, который содержит пару ключ-значение в формате
"Type": "...:DualEndPoint"
, а объект Local
является то же самое, но с DualEndPoint
, замененным на Local
. Если эта интерпретация верна, то в вашем первом фрагменте кода будет три примера Local
объектов на двух разных уровнях вложенности (что я понимаю как «нелинейная» часть).
Один из примеров объекта Local
будет следующим:
{
"Type": "Endpoint:Src:Local",
"User": "user1",
"Port": "0",
"OsType": "Windows",
"HostName": "Local",
"Password": "newpassword",
"HomeDirectory": "/user1homedir"
}
Нет примеров подобных объектов, которые, несмотря на наличие атрибута «Пользователь», не должны обновляться. Таким образом, похоже, что для ответа на вопрос, различие между этими типами объектов также совершенно не нужно?
Мне нужно иметь возможность запросить определенного пользователя c в атрибуте «Пользователь» и вставьте новый пароль для повторной отправки обратно в API.
Таким образом, подзадача вашей главной проблемы может состоять в том, чтобы обновить объект с новым паролем, если он правильный User
. Предполагая, что вы ограничили объект до такого объекта, часть программы может выглядеть следующим образом:
$ jq 'if .User == "user1" then .Password = "derp" else . end' local1.json
{
"Type": "Endpoint:Src:Local",
"User": "user1",
"Port": "0",
"OsType": "Windows",
"HostName": "Local",
"Password": "derp",
"HomeDirectory": "/user1homedir"
}
Для DualEndPoints имена вложенных объектов являются переменными, поэтому нельзя кодировать их значения в поиске атрибута «Пользователь».
Похоже, вы хотите произвольно повторить поиск объектов с атрибутами «Пользователь». Некоторые из рекурсивных комбинаторов jq: ..
, более общий recurse
и, что представляется более уместным в этом контексте, walk
:
$ jq 'walk(if type == "object" and .User == "user1"
then .Password = "derp"
else . end)' full.json
(Это также что написал Аарон, за исключением того, что он использует |=
, а я использую =
.)
См. его пример jqplay или этот пример jqplay .
Где совпадение для указанного пользователя c найдено, возвращает всю структуру, в которой вставлен только новый пароль этого пользователя. В этом примере запрос для user1 вернул бы весь PROFILE1 и PROFILE2, но не PROFILE3, поскольку он не содержит учетные данные user1.
Это звучит как дополнительное условие в выражении, с которым мы ходим:
$ jq 'walk(if type == "object" and has("User")
then (if .User == "user1"
then .Password = "derp"
else null end)
else . end)' full.json
Похоже, что это почти работает (см. в этом примере jqplay ), за исключением того, что он оставляет значения "foo": null
в результате ходьбы. Это побочный продукт того, что мы уже вернулись в объект, содержащий свойство «Пользователь», что затрудняет express удаление родительской пары ключ-значение.
Исправление этого нам нужно либо посмотреть в фильтр walk/1
, либо создать заполнитель и пройти второй раз с точки зрения родительского объекта. Последняя из этих двух стратегий демонстрируется здесь:
$ jq 'walk(if type == "object" and has("User")
then (if .User == "user1" then .Password = "derp" else "wat" end)
else . end)
| walk(if type == "object"
then with_entries(select(.value != "wat"))
else . end)' full.json
Это работает. Смотрите этот пример jqplay .