PowerShell 3.0+
PowerShell 3.0 以降 (「インストールされている PowerShell のバージョンを確認する」を参照) では、ConvertFrom-Json
コマンドレットを使用して JSON 文字列を PowerShell データ構造に変換できます。
これは便利であると同時に残念なことです。JSON を使用するのは非常に簡単なので便利ですが、 PSCustomObjectsConvertFrom-Json
が得られるのは残念なことであり、それらはキーと値のペアとして繰り返し処理するのが難しいためです。
キーがわかっている場合は、反復する必要はありません。たとえば、キーに直接アクセスするだけで$result.thisKey.then.thatKey.array[1]
完了です。
"17443"
しかし、この特定の JSON では、キーは動的であるか、またはのように事前に知られていないよう"17444"
です。つまり、aを理解できるPSCustomObject
キーと値のリストに変換できるものが必要ですforeach
。
# helper to turn PSCustomObject into a list of key/value pairs
function Get-ObjectMember {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$True, ValueFromPipeline=$True)]
[PSCustomObject]$obj
)
$obj | Get-Member -MemberType NoteProperty | ForEach-Object {
$key = $_.Name
[PSCustomObject]@{Key = $key; Value = $obj."$key"}
}
}
これで、オブジェクト グラフをトラバースし、出力オブジェクトのリストを生成できTitle
ますFirstName
。LastName
$json = '{"17443": {"17444": {"sid": "17444","nid": "7728","submitted": "1436891400","data": {"3": {"value": ["Miss"]},"4": {"value": ["Charlotte"]},"5": {"value": ["Tann"]}}},"17445": {"sid": "17445","nid": "7728","submitted": "1437142325","data": {"3": {"value": ["Mr"]},"4": {"value": ["John"]},"5": {"value": ["Brokland"]}}},"sid": "17443","nid": "7728","submitted": "1436175407","data": {"3": {"value": ["Mr"]},"4": {"value": ["Jack"]},"5": {"value": ["Cawles"]}}}}'
$json | ConvertFrom-Json | Get-ObjectMember | foreach {
$_.Value | Get-ObjectMember | where Key -match "^\d+$" | foreach {
[PSCustomObject]@{
Title = $_.value.data."3".value | select -First 1
FirstName = $_.Value.data."4".value | select -First 1
LastName = $_.Value.data."5".value | select -First 1
}
}
}
出力
役職 名 姓
----- --------- --------
ミス・シャーロット・タン
ジョン・ブロックランド氏
PowerShell 2.0 / 代替アプローチ
PowerShell 2.0 (上記の構成の一部をサポートしていない) でも機能する別のアプローチでは、.NET JavaScriptSerializer クラスを使用して JSON を処理します。
Add-Type -AssemblyName System.Web.Extensions
$JS = New-Object System.Web.Script.Serialization.JavaScriptSerializer
JavaScriptSerializer は通常のDictionariesを提供するため、非常によく似た操作を実行できます。これは、GetEnumerator()
メソッドを介してキーと値のペアとして簡単に反復処理できます。
$json = '{"17443": {"17444": {"sid": "17444","nid": "7728","submitted": "1436891400","data": {"3": {"value": ["Miss"]},"4": {"value": ["Charlotte"]},"5": {"value": ["Tann"]}}},"17445": {"sid": "17445","nid": "7728","submitted": "1437142325","data": {"3": {"value": ["Mr"]},"4": {"value": ["John"]},"5": {"value": ["Brokland"]}}},"sid": "17443","nid": "7728","submitted": "1436175407","data": {"3": {"value": ["Mr"]},"4": {"value": ["Jack"]},"5": {"value": ["Cawles"]}}}}'
$data = $JS.DeserializeObject($json)
$data.GetEnumerator() | foreach {
$_.Value.GetEnumerator() | where { $_.Key -match "^\d+$" } | foreach {
New-Object PSObject -Property @{
Title = $_.Value.data."3".value | select -First 1
FirstName = $_.Value.data."4".value | select -First 1
LastName = $_.Value.data."5".value | select -First 1
}
}
}
出力は同じです。
役職 名 姓
----- --------- --------
ミス・シャーロット・タン
ジョン・ブロックランド氏
JSON が 4 MB を超える場合は、それに応じてJavaScriptSerializer.MaxJsonLength
プロパティを設定します。
ファイルからの JSON の読み取りについて
ファイルから読み取る場合は、Get-Content -Raw -Encoding UTF-8
.
-Raw
そうしないGet-Content
と、個々の行の配列が返され、それJavaScriptSerializer.DeserializeObject
を処理できないためです。最近の Powershell バージョンでは、.NET 関数の引数の型変換が改善されているようです。そのため、システムでエラーが発生しない可能性がありますが、エラーが発生した場合 (または安全のために) -Raw
、.
-Encoding
テキスト ファイルを読み取るときにエンコーディングを指定するのが賢明でありUTF-8
、JSON ファイルの最も可能性の高い値であるためです。
ノート
- 予測できないキーを持つアイテムを含む JSON を構築する場合は、よりも配列構造を優先
{items: [{key: 'A', value: 0}, {key: 'B', value: 1}]}
して{'A': 0, 'B': 1}
ください。後者の方が直感的に見えますが、生成するのも消費するのも難しいです。
ConvertFrom-Json()
PSCustomObject
JSON 文字列のデータを反映する PowerShell カスタム オブジェクト ( ) を提供します。
- カスタムオブジェクトのプロパティをループできます
Get-Member -type NoteProperty
$object."$propName"
構文、alternativeを使用して、オブジェクトのプロパティに動的にアクセスできます$object."$(some PS expression)"
。
- 独自のカスタム オブジェクトを作成し、一連のプロパティで初期化でき
New-Object PSObject -Property @{...}
ます[PSCustomObject]@{ .. }
。