То, что я пытаюсь сделать, это взять любой правильно сформированный файл / объект JSON и найти путь внутри него. Если путь не найден, двигайтесь дальше. Если он найден, обновите значение. После обновления сохраните обновленный JSON в исходный файл.
Подвох в том, что правильно сформированная структура JSON не известна заранее. Возможно, я искал сотни файлов .json на диске, поэтому файлы, которые не соответствуют ни одному из моих условий поиска, можно просто игнорировать.
Я изо всех сил стараюсь решить, как решить эту проблему. В большинстве примеров отсутствует объект JSON с массивом для одного из ключевых значений или они не обращаются к свойствам динамически, когда задействован массив.
Эта ссылка: Powershell: как обновить / заменить данные и значения в Json и объекте XML показывает (своего рода) "реальную" структуру JSON, но принятый ответ опирается на знание структуры JSON есть (ОП не обращался за помощью по динамическому пути).
Эта ссылка: Задать значение свойства вложенного объекта по имени в PowerShell имеет что-то очень близкое, хотя, когда массив находится в миксе, он не работает должным образом при настройке.
Ниже приведен пример использования JSON для решения этой проблемы, хотя, опять же, структура не известна до запуска сценария. Я перебираю список файлов на диске и выполняю для каждого файла.
$JSON = ConvertFrom-Json '{
"key1":"key 1 value",
"options":{
"outDir":"./app-dir",
"lib":[
"someLibrary",
"anotherLibrary"
],
"someObjects":[
{
"first":"I am first"
},
{
"second":"I am second"
}
]
}
}'
Строка для поиска этого json может выглядеть следующим образом:
$SearchString = 'options.someObjects.first'
Или, может быть, что-то несуществующее, как:
$SearchString = 'options.someObjects.foo'
Использование рекурсивной функции GetValue из 2-й статьи прекрасно работает для получения (и гораздо более элегантно, чем то, что я делал):
function GetValue($object, $key)
{
$p1,$p2 = $key.Split(".")
if($p2) { return GetValue -object $object.$p1 -key $p2 }
else { return $object.$p1 }
}
Однако функция SetValue не работает с массивом. Он возвращает ошибку о том, что «свойство first не может быть найдено для этого объекта».
function SetValue($object, $key, $Value)
{
$p1,$p2 = $key.Split(".")
if($p2) { SetValue -object $object.$p1 -key $p2 -Value $Value }
else { $object.$p1 = $Value }
}
Я знаю, что это потому, что $ JSON.options.someObjects является массивом, поэтому для доступа к объекту с помощью «первого» ключа путь будет:
$JSON.options.someObjects[0].first
Это проблема, с которой я столкнулся. Как мне динамически перебирать все объекты, как только они достигают части пути, которая нуждается в переборах? Эта часть пути может быть где угодно, или больше уровней внизу и т. Д.
Странно, что powershell позволит вам динамически перебирать массив при получении значения, но не при попытке его установить.
Вот полный пример, который демонстрирует всю проблему:
#Create JSON:
$JSON = ConvertFrom-Json '{
"key1":"key 1 value",
"options":{
"outDir":"./app-dir",
"lib":[
"someLibrary",
"anotherLibrary"
],
"someObjects":[
{
"first":"I am first"
},
{
"second":"I am second"
}
]
}
}'
$SearchPath = 'options.someObjects.first'
$NewValue = 'I am a new value'
function GetValue($object, $key)
{
$p1,$p2 = $key.Split(".")
if($p2) { GetValue -object $object.$p1 -key $p2 }
else { return $object.$p1 }
}
function SetValue($object, $key, $Value)
{
$p1,$p2 = $key.Split(".")
if($p2) { SetValue -object $object.$p1 -key $p2 -Value $Value }
else { return $object.$p1 = $Value }
}
GetValue -object $JSON -key $SearchPath
SetValue -object $JSON -key $SearchPath -Value $NewValue
Я искал всевозможные термины, пытаясь найти хорошее решение для этой проблемы, но пока безуспешно. Я вполне уверен, что я не первый человек, который хочет делать подобные вещи, извинения, если я где-то пропустил ответ.