2016-04-14 4 views
3

デフォルトでは、PowerShellのConvertFrom-JsonコマンドレットはJSONドキュメントの参照を処理していないようです。ConvertFrom-Jsonを使用したJSONリファレンスの処理

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

私は本当にこのJSON仕様の公式の状況を知らない(herehereを参照)が、PowerShellではそのようなことを管理する方法はありますか?

答えて

1

AFAIK JSONリファレンスを解決する組み込みの方法はありません。私は通常、PowerShellでサポートされていない問題のために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

マン、これはそれです!どうもありがとうございます。ところで、powershellのためのそのような機能poc上のMSの姿勢は何ですか?彼らは機能の推奨ページなどを持っていますか? –

+1

はい、Uservoice https://windowsserver.uservoice.com/forums/301869-powershellに提案を投稿してください –

関連する問題