PowerShellでJSONから値を取得する方法|ConvertFrom-Jsonの使い方

Powershell Powershell
この記事は約11分で読めます。

PowerShellでは、ConvertFrom-Json を利用することでJSON形式のデータをPowerShellのオブジェクトとして扱うことができます。

JSONファイルから特定の値を取得したり、配列の中から条件に一致するデータを取得したりする場合に便利なコマンドです。

今回は、PowerShellでJSONを読み込み、以下のような操作を試してまとめてみました。

  • JSONファイルから特定の値を取得する
  • JSONの配列から特定の値を取得する
  • 条件に一致するデータを取得する
  • JSONファイルを読み込むときのGet-Content -Rawの使い方
  • JSON文字列を直接PowerShellオブジェクトに変換する

1.PowerShellでJSONから値を取得する基本

PowerShellでJSONを扱う場合は、ConvertFrom-Json を利用します。

ConvertFrom-Json は、JSON形式の文字列をPowerShellのオブジェクトに変換するコマンドです。

例えば、以下のようなJSONがあるとします。

{
  "name": "hoge",
  "id": "001",
  "location": "Japan"
}

このJSONをPowerShellで読み込むと、それぞれの項目をプロパティとして参照できます。

$json = '{
  "name": "hoge",
  "id": "001",
  "location": "Japan"
}' | ConvertFrom-Json

$json.name

実行結果は以下のようになります。

PS C:\> $json.name
hoge

同じように、id や location も取得できます。

PS C:\> $json.id
001
PS C:\> $json.location
Japan

このように、JSONを ConvertFrom-Json で変換しておけば、JSONの項目を.プロパティ名という形で取得できます。

2. JSONファイルから値を取得する

次に、JSON形式で保存されたファイルから値を取得してみます。

今回は以下のようなJSONファイルを用意します。

{
  "title": "hogehoge",
  "values": [
    {
      "name": "hoge01",
      "id": "001",
      "properties": {
        "Number": "0001",
        "animal": [
          "cat",
          "monkey",
          "elephant"
        ],
        "location": [
          "Australia",
          "Japan",
          "China"
        ]
      }
    },
    {
      "name": "hoge02",
      "id": "002",
      "properties": {
        "Number": "0002",
        "animal": [
          "cat02",
          "monkey02",
          "elephant02"
        ],
        "location": [
          "Australia",
          "Japan",
          "China"
        ]
      }
    },
    {
      "name": "hoge03",
      "id": "003",
      "properties": {
        "Number": "0003",
        "animal": [
          "cat03",
          "monkey03",
          "elephant03"
        ],
        "location": [
          "Australia",
          "Japan",
          "China"
        ]
      }
    }
  ]
}

このJSONファイルから elephant を取得してみます。

2-1. PowerShellコマンド

以下のPowershellコマンドで elephant を取り出すことが可能です。

$Path = "C:\hogehoge\hogehoge.json"
$json = Get-Content $Path | ConvertFrom-Json
$get_animal = $json.values.properties.animal[2]
$get_animal

・実行結果

PS C:\> $Path = "C:\hogehoge\hogehoge.json"
PS C:\> $json = Get-Content $Path | ConvertFrom-Json
PS C:\> $get_animal = $json.values.properties.animal[2]
PS C:\> $get_animal
elephant

2-2. コマンドのポイント

今回の処理では、以下の順番でJSONを読み込んでいます。

JSONファイル
   ↓
Get-Content -Raw
   ↓
ConvertFrom-Json
   ↓
PowerShellオブジェクト
   ↓
プロパティを指定して値を取得

Get-Content の -Raw を指定すると、ファイル全体を1つの文字列として取得できます。

その文字列を ConvertFrom-Json に渡すことで、JSONをPowerShellのオブジェクトとして扱えるようになります。

Microsoftの公式ドキュメントでも、JSONファイルを読み込む例として Get-Content -Raw JsonFile.json | ConvertFrom-Json が紹介されています。

ConvertFrom-Json (Microsoft.PowerShell.Utility) – PowerShell
The ConvertFrom-Json cmdlet converts a JavaScript Object Notation (JSON) formatted string to a custom PSObject or Hashta…

3.JSONの階層が深い場合の値の取得方法

JSONでは、項目の中にさらに項目が存在することがあります。

今回のJSONでは、以下のような階層になっています。

values
 └─ properties
     └─ animal
         ├─ cat
         ├─ monkey
         └─ elephant

そのため、以下のように指定すると、elephant を取得できます。

$json.values[0].properties.animal[2]

それぞれの意味は以下のとおりです。

指定意味
$jsonJSON全体
.valuesvaluesを取得
[0]valuesの1件目
.propertiespropertiesを取得
.animalanimalを取得
[2]animalの3番目

PowerShellの配列は0から数えるため、[2] は3番目の値を意味します。

4. JSONの配列から条件を指定して値を取得する

また、配列の中から特定の項目だけを取得したいケースもあります。

例えば、先ほどのJSONから、name = hoge02 に一致するデータの animal の値を取得してみます。

4-1. PowerShellコマンド

$Path = "C:\hogehoge\hogehoge.json"
$json = Get-Content -Path $Path -Raw | ConvertFrom-Json
$hoge02 = $json.values | Where-Object {$_.name -eq "hoge02"}
$hoge02.properties.animal

・実行結果

PS C:\> $Path = "C:\hogehoge\hogehoge.json"
PS C:\> $json = Get-Content -Path $Path -Raw | ConvertFrom-Json
PS C:\> $hoge02 = $json.values | Where-Object {$_.name -eq "hoge02"}
PS C:\> $hoge02.properties.animal
cat02
monkey02
elephant02

Where-Object を利用すると、配列の中から条件に一致するオブジェクトを取得できます。

(参考)3行目と4行目の取り出しイメージ

特定の値に対応した項目一覧を抽出するPowershellコマンドの3行目と4行目の取り出しイメージ

4-2. idを指定してJSONから値を取得する

name ではなく、id を条件にすることもできます。

例えば、id = 002 のデータを取得する場合は以下のように取り出すことが可能です。

$hoge02 = $json.values | Where-Object {$_.id -eq "002"}
$hoge02.properties.animal

実行結果は name を条件とした時と同じ結果となります。

PS C:\> $hoge02 = $json.values | Where-Object {$_.id -eq "002"}
PS C:\> $hoge02.properties.animal
cat02
monkey02
elephant02

5. JSONから複数の値をまとめて取得する

JSONの中に複数の配列が存在する場合でも、同じように取得できます。

例えば、以下のコマンドを実行すると、location に格納されている値がすべて取得できます。

$json.values[0].properties.location

・実行結果

PS C:\> $json.values[0].properties.location
Australia
Japan
China

特定の値だけ取得する場合は、配列のインデックスを指定します。

PS C:\> $json.values[0].properties.location[1]
Japan

6.JSONファイルを読み込むときに「-Raw」を付ける理由

JSONファイルを読み込むときは、以下のように -Raw を付ける方法がおすすめです。

$json = Get-Content -Path $Path -Raw | ConvertFrom-Json

Get-Content は、通常はファイルを行単位の文字列として取得します。

一方、-Raw を指定すると、ファイル全体を1つの文字列として取得します。

JSONは複数行で記述されることが多いため、JSONファイル全体を1つの文字列として取得してから ConvertFrom-Json に渡す形にしないと改行位置でJSONが壊れたり、パースエラーになったりする可能性があるからです。

そのため、JSONファイルを読み込む場合は、以下の書き方を基本形とするのがよいと思います。

$json = Get-Content -Path "C:\hogehoge\hogehoge.json" -Raw | ConvertFrom-Json

7.Get-ContentだけではJSONの値を取得できない?

ConvertFrom-Json を使わず、Get-Content だけでJSONファイルを読み込むこともできます。

ですが、この場合、ファイルの中身を文字列として扱うためpowershell上で特定の値を変数に入れることが難しくなります。

 ※やろうと思えば可能ですが、何文字目から何文字目まで取得する などといった非常にめんどくさいことをしなければなりません。

以下、Get-Content を利用してファイルの内容を読み込んだ場合に、JSONのプロパティを利用して、値を取得した場合の実行結果です。

PS C:\> $Path = "C:\hogehoge\hogehoge.txt"
PS C:\> $json = Get-Content $Path
PS C:\> $get_animal = $json.values.properties.animal[2]
null 配列にインデックスを付けることはできません。
発生場所 行:1 文字:1
+ $get_animal = $json.values.properties.animal[2]
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) []、RuntimeException
    + FullyQualifiedErrorId : NullArray

PS C:\>

上記のようにエラーが出力されます。

これは、Get-Content を利用してファイルを読み込んだ場合、変数 $json にはファイルの内容が「文字列」として格納されているためです。

以下を実行してみるとファイルの中身が文字列として扱われていることがわかります。

PS C:\> $json[15]
h
PS C:\>
PS C:\> $json[12]
:
PS C:\>

8.APIから取得したJSONを扱う場合

Web APIからJSONを取得する場合は、Invoke-RestMethod を利用すると便利です。

Invoke-RestMethod はJSONレスポンスをPowerShellのオブジェクトとして扱えるため、別途ConvertFrom-Json を実行しなくてもプロパティを参照できます。

$result = Invoke-RestMethod -Uri "https://hogehoge.com"
$result.id

実際の実行例としては、以下の記事でも記載しているMicrosoft365のURL・IPアドレスの一覧の情報を取得する場合にも利用できます。

Microsoft 365のURL・IPアドレス一覧を確認・取得する方法
Microsoft 365では、Exchange Online、SharePoint Online、Teamsなどのサービスを利用するために、さまざまなURLやIPアドレスへの通信が発生します。Microsoftでは、Microsoft 365で利用されるURLやIPアドレスの情報を公開しています。この記事では、Microsoft 365のURL・IPアドレス情報を確認する方法と、PowerShellを使って取得する方法を紹介します。
PS C:\> $result = Invoke-RestMethod -Uri "https://endpoints.office.com/endpoints/worldwide?clientrequestid=b10c5ed1-bad1-445f-b386-b919946339a7"
PS C:\> $result.serviceAreaDisplayName
Exchange Online
Exchange Online
Exchange Online
Exchange Online
Exchange Online
Microsoft Teams
Microsoft Teams
Microsoft Teams
 ・
 ・
 ・

9.さいごに

私がpowershellを触り始めた時は、ConvertFrom-Json というコマンドを知らなかったため、取り出したい値を取り出すことができずに苦戦していました。

ですが、ConvertFrom-Json を知ってからは、「取り出したい値を取り出して変数として利用し、後続の処理に渡す」ということを自然とできるようになり、今ではスクリプトなどでかなり活用しています。