PowerShellでJSONファイルを読み込む|ConvertFrom-Jsonで値を取り出す

JSONファイルをPowerShellで表示できても、名前やポート番号だけを取り出そうとすると、文字列のままで扱いにくいことがあります。設定値をスクリプトで使うなら、ファイルの全文を読み、ConvertFrom-Jsonでオブジェクトに変換すると、項目名から値へアクセスできます。

ここでは小さなJSONファイルを作り、プロパティ、配列、解析エラーの扱いを順に試します。例はWindows PowerShell 5.1とPowerShell 7で使える書き方です。


サンプルのJSONファイルを作る

自分の設定ファイルとは別の、新しい作業フォルダーを使ってください。次の例はjson-read-demoを作り、その中へUTF-8のsettings.jsonを書き込みます。同名フォルダーがある場合は別の名前を選ぶと、既存のファイルを上書きせずに試せます。

New-Item -ItemType Directory -Path .\json-read-demo -ErrorAction Stop | Out-Null
Set-Location -LiteralPath .\json-read-demo
@'
{
  "name": "demo",
  "enabled": true,
  "ports": [8080, 8443]
}
'@ | Set-Content -LiteralPath .\settings.json -Encoding UTF8

JSONでは項目名と文字列を二重引用符で囲み、真偽値はtrueまたはfalseと書きます。PowerShellの連想配列とは記法が異なるため、@{ name = 'demo' }をそのままJSONファイルへ書くと解析できません。

全文を変換して項目の値を取り出す

Get-Content -Rawで全文を1つの文字列として読み、それをConvertFrom-Jsonへ渡します。-LiteralPathはファイル名をそのまま指定するためのオプションです。文字コードがUTF-8のファイルには、例のように-Encoding UTF8を指定できます。

$config = Get-Content -LiteralPath .\settings.json -Encoding UTF8 -Raw |
    ConvertFrom-Json -ErrorAction Stop
$config.name
$config.enabled
$config.ports[0]

項目名をドットの後ろへ書くと値を取得できます。portsは配列なので、最初の要素は[0]です。次の出力では、JSONのtrueがPowerShellの真偽値としてTrueと表示されます。

demo
True
8080

全文の読み取りと行ごとの読み取りの違いは、Get-Contentの-Rawと行配列の使い分けでも説明しています。JSONの解析には、改行を含む文書全体を渡す形が分かりやすくなります。ファイルがUTF-8以外で保存されている場合は、その文字コードに合う読み取り方法が必要です。

JSON配列の要素を取り出す

JSON全体が[...]の配列なら、変換結果を変数へ代入してから要素にアクセスします。次はファイルを使わず、2件のデータを文字列として変換する例です。

$items = '[{"name":"alpha"},{"name":"beta"}]' | ConvertFrom-Json
$items.Count
$items[1].name

2件あるためCountは2、2番目の要素のnameはbetaになります。

2
beta

PowerShell 5.1と7では、JSON配列をパイプラインへ出すときの扱いに違いがあります。上の例を@('...' | ConvertFrom-Json)で包むと、5.1では配列全体が外側の配列の1要素になるため、同じCountや添字で同じ結果を得られません。両方でこの例を使うなら、まず変換結果を直接代入する書き方が適しています。

データが1件や0件になるスクリプトでは、その場合の値の形も考慮が必要です。PowerShell 7には-NoEnumerateがありますが、Windows PowerShell 5.1では使えません。上の2件の例をそのまま、件数が変わる処理すべてに一般化しないようにしてください。

壊れたJSONをエラーとして処理する

閉じ括弧の不足などでJSONが壊れている場合は、解析時にエラーになります。後続処理へ進めたくないときは-ErrorAction Stopを付け、tryとcatchで失敗時の処理を用意できます。

try {
    '{"name":' | ConvertFrom-Json -ErrorAction Stop | Out-Null
} catch {
    'Invalid JSON'
}

この入力は途中で途切れているため、catch内の文字列が出力されます。

Invalid JSON

空の入力やJSONのnullは、この構文エラーと同じ扱いにはなりません。また、解析できても必要な項目があるとは限りません。実際の設定を読み込む処理では、入力が空でないことや、使う項目・値がそろっていることも確認する必要があります。

コメントの扱いにも版の違いがあります。Windows PowerShell 5.1のConvertFrom-Jsonはコメントを含むJSONでエラーになります。5.1と7で同じファイルを使うなら、コメントを入れず、項目名と文字列を二重引用符で囲んだJSONを用意すると扱いやすくなります。

読み取れないときに見るポイント

  • ファイルが見つからない場合は、現在の作業フォルダーと-LiteralPathに渡すパスを確かめます。
  • 文字が崩れる場合は、ファイルの保存時の文字コードと読み取り時の-Encodingを合わせます。
  • 変換時にエラーになる場合は、引用符、カンマ、括弧、5.1でのコメントの有無を見直します。
  • 値を取得できない場合は、JSONの項目名、入れ子の位置、配列の添字を見ます。

ファイルの読み取り、JSONの解析、項目の取り出しを順に確かめると、どこで値が変わったかを追いやすくなります。まずは小さなサンプルで期待する値を取り出してから、使いたいJSONへ置き換えると、問題の原因を絞り込めます。

参考資料

このブラウザからの自分のアクセスを解析から除外できます。