2016-04-14 2 views
3

По умолчанию командлет PowerShell ConvertFrom-Json, похоже, не обрабатывает ссылки в документах JSON.Обработка справки JSON с ConvertFrom-Json

{ 
    "foo": {"$ref": "#/bar"}, 
    "bar": true 
} 

Я не знаю об официальном статусе этого JSON спецификации (см here и here), но есть способ управлять такой вещью в PowerShell?

ответ

1

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 
+0

Человек, это он! Огромное спасибо. Кстати, какова позиция MS по такой функции poc для powershell? У них есть страница с рекомендациями по функции или что-то подобное? –

+1

Да, опубликуйте предложение по Uservoice https://windowsserver.uservoice.com/forums/301869-powershell –

Смежные вопросы