AFAIK нет встроенных способов решения JSON-ссылок. Обычно я ищу решение для C# для проблемы, которая не поддерживается в PowerShell, поскольку они могут быть преобразованы в PowerShell-код большую часть времени, но я не мог найти простой способ сделать это на C# без специального кода.
Поэтому, я думаю, вам, возможно, потребуется написать некоторые функции самостоятельно и использовать что-то вроде Invoke-Expression
и ссылочные типы (которые преобразованный объект является таким, как PSCustomObject), чтобы помочь вам.
Доказательство концепции (содержит много ошибок):
$json = @'
{
"foo": {"$ref": "#/bar"},
"bar": true
}
'@
$t = ConvertFrom-Json -InputObject $json
Write-Host "Before"
$t | Out-Host
function resolveReferences ($obj) {
#Loop through propeties
$obj.psobject.Properties | ForEach-Object {
#ref-values are PSCustomObjects with a $ref-property, so let's find the PSCustomObjects
if ($_.TypeNameOfValue -eq 'System.Management.Automation.PSCustomObject') {
#Verify it was a ref-value by checking for $ref-property
if ($_.Value.'$ref') {
#Convert value to powershell-path like $t.foo
$refpath = $_.Value.'$ref'.Replace("#/",'$t.').Replace("/",".")
#Execute generated powershell-path to get the referenced object and replace reference with the referenced object
$_.Value = (Invoke-Expression -Command $refpath)
}
}
}
}
resolveReferences -obj $t
Write-host "After"
$t | Out-Host
Выход:
Before
foo bar
--- ---
@{$ref=#/bar} True
After
foo bar
--- ---
True True
Что можно расширить, чтобы соответствовать вашим потребностям. Ex. поддержка массива объектов:
$json = @'
{
"foo": {"$ref": "#/bar"},
"fooarray": [
{"item": {"$ref": "#/bar"}},
{"item": {"$ref": "#/hello"}}
],
"test": [1,2,3],
"bar": true,
"hello": "world"
}
'@
$t = ConvertFrom-Json -InputObject $json
Write-Host "Before"
$t | Out-Host
function resolveReferences ($obj) {
$obj.psobject.Properties | ForEach-Object {
if ($_.TypeNameOfValue -eq 'System.Management.Automation.PSCustomObject') {
if ($_.Value.'$ref') {
$refpath = $_.Value.'$ref'.Replace("#/",'$t.').Replace("/",".")
$_.Value = (Invoke-Expression -Command $refpath)
}
} elseif ($_.TypeNameOfValue -eq 'System.Object[]') {
#If array, loop through objects (recursive search)
$_.Value | ForEach-Object { resolveReferences -obj $_ }
}
}
}
resolveReferences -obj $t
Write-host "After"
$t | Out-Host
Выход:
#item properties in fooarray-objects are ref paths, it's just PS being to lazy to go deeper and show their values
Before
foo : @{$ref=#/bar}
fooarray : {@{item=}, @{item=}}
test : {1, 2, 3}
bar : True
hello : world
After
foo : True
fooarray : {@{item=True}, @{item=world}}
test : {1, 2, 3}
bar : True
hello : world
Человек, это он! Огромное спасибо. Кстати, какова позиция MS по такой функции poc для powershell? У них есть страница с рекомендациями по функции или что-то подобное? –
Да, опубликуйте предложение по Uservoice https://windowsserver.uservoice.com/forums/301869-powershell –