2

json ファイルから PSObject を作成しています

bar.json

{
  "derp": {
   "buzz": 42 
   },
   "woot":  {
     "toot": 9000
   }
}

ConvertFrom-Json を使用して JSON から PSCustomObject を作成できます

$foo = Get-Content .\bar.json -Raw |ConvertFrom-Json
$foo.gettype()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     False    PSCustomObject                           System.Object

ただし、複数のjsonファイルをスプラットしようとすると、配列が得られます

$foo = Get-Content .\*.json -Raw |ConvertFrom-Json
$foo.gettype()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     False    Object[]                                 System.Array

$foo を反復するには、オブジェクトの種類に応じて 2 つの異なるコード パスが必要です。

複数の json ファイルから単一のオブジェクトを取得できますか?
そうでない場合、オブジェクトの配列を単一のオブジェクトに圧縮するにはどうすればよいですか?

$barのすべての配列項目を含む新しいオブジェクトを作成しようとしました$foo

$bar = new-object psobject
$bar | add-member -name $foo[0].psobject.properties.name -value $foo[0].'derp' -memberType NoteProperty


Walter Mitty の要求に従って更新します。単一のファイルをロードして実行すると$foo[0]

$foo = Get-Content .\bar.json -Raw |ConvertFrom-Json
$foo[0].gettype()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     False    PSCustomObject                           System.Object

$foo[0]

derp                                                    woot
------------                                            ------------
@{Provisioners=System.Object[]; OS=windows; Size=; V... @{Provisioners=System.Object[]; OS=windows; Size=; V...

解決

最初に AP の回答を実装しましたが、後で mklement0 の回答を使用するようにリファクタリングしました。

$allObjects は配列ですが、探していた名前で値を参照できます

$allObjects = @(
    Get-ChildItem '.\foo' -Filter *.json -Recurse | Get-Content -Raw | ConvertFrom-Json
)

# iterating over nested objects inside an array is hard.
# make it easier by moving all array objects into 1 parent object where 
# the 'key' is the name (opposed to AP's answer where filename = key)
$newObject = New-Object PSObject
foreach ($i in $allObjects) {
    $i.psobject.members | ?{$_.Membertype -eq 'noteproperty'} |%{$newObject | add-member $_.Name $_.Value}
}
4

2 に答える 2

3

必要なのは、さまざまなファイルから解析された JSON オブジェクトの配列だけである場合:

$final = @{}

# Loop Thru All JSON Files, and add to $Final[<name>] = <JSON>
ls .\*.json | % {
  $o = cat $_ -Raw | ConvertFrom-Json
  $final[$_.name] = [PsCustomObject]$o
}
$final = [PsCustomObject]$final

これにより、ネストされたすべての JSON ファイルの Name -> Data マップが生成されますPSObject

于 2016-12-09T18:23:04.943 に答える
2

AP. の役立つ回答は、次のような単一のトップレベル オブジェクト ([pscustomobject]インスタンス) を作成するためのエレガントなソリューションです。

  • JSON に変換されたすべてのオブジェクトを、入力ファイル名にちなんで名付けられたプロパティとして格納します。

    • たとえば、値が質問の JSON 文字列に相当するオブジェクトで$finalあるプロパティが含まれます。bar.json

    • 注意点は、ファイル名が重複していると、最後に処理されたファイルが「勝つ」ことです。

Unix スタイルのエイリアスlscat.


JSON から変換されたすべてのオブジェクトの配列取得するには、次のようにすれば十分です。

$allObjects = @(Get-ChildItem -Filter *.json | Get-Content -Raw | ConvertFrom-Json)

単一のディレクトリの JSON ファイルのみが必要な場合でも
$allObjects = @(Get-Content -Path *.json -Raw | ConvertFrom-Json)機能することに注意してください。

単一のオブジェクトのみが返される場合でも、返されるものが配列@(...)として扱われることを保証する、配列部分式演算子の使用に注意してください。

  • 既定では、または通常$(...)の部分式演算子を使用すると、PowerShell は (ネストされている可能性がある) 単一アイテム コレクションをラップ解除し、アイテム自体のみを返します。を参照してください。Get-Help about_Operators

lsUnix スタイルのエイリアスとcat、PowerShellGet-ChildItemおよびコマンドレットのそれぞれの使用に関する注意Get-Content:

  • PowerShell はクロスプラットフォームであるため、これらのエイリアスは PowerShell のWindowsエディションにのみ存在しますが、Unix プラットフォームの PowerShell Core からはそれらを除外することが決定されました。これにより、同じ名前の標準の Unix ユーティリティが隠れないようにします。

  • 所定の命名規則に従い、プラットフォーム固有のユーティリティと競合しない、PowerShell独自のエイリアスを使用する習慣を身につけることをお勧めします。

    • たとえば、、およびにgci使用できますGet-ChildItemgcGet-Content
    • PowerShell 独自のエイリアスの背後にある命名規則については、ドキュメントを参照してください。
于 2016-12-09T21:21:07.427 に答える