JSON形式で記載されたテキストファイルやJSONファイルの中から [ConvertFrom-Json] を利用して特定の値を取り出す方法についてまとめてみました。
記事内下部の「[参考] Get-Contentでファイルを読み込んだ場合の挙動」でも記載していますが、テキストファイルやJSONファイルは、そのまま読み込むと文字列として認識されるので特定の値を取り出すということが難しいです。
[ConvertFrom-Json] を利用することで、JSON形式のファイルの特定の項目を変数として使うことができるので、そういったことをやりたいときの参考にしていただければと思います。
また、似たような値の取り出し方として特定の値に対応した項目一覧を抽出する方法も合わせて紹介していきます。
1.JSON形式のファイルから特定の値を取り出す
今回は以下のjson形式のテキストファイルを利用します。
・hogehoge.txt
{
"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"
]
}
}
]
}
そして以下のPowershellコマンドで、
json形式で記載されたtxtファイル(今回はhogehoge.txt)を読み込み、
その中に記載された特定の値(今回はelephant)を取り出します。
Powershellスクリプト
$Path = "C:\hogehoge\hogehoge.txt"
$json = Get-Content $Path | ConvertFrom-Json
$get_animal = $json.values.properties.animal[2]
$get_animal
スクリプトの解説
1行目では、ファイルのフルパスを変数[$Path]として格納します。
2行目では、[Get-Content]というコマンドを利用して、変数[$Path]のファイルから情報を読み取ります。
しかし、この状態では「文字列」として認識されていますので、|(パイプ)で値を渡して[ConvertFrom-Json]というコマンドを実行します。
3行目では、目的の値(今回はelephant)をJSON形式のファイルから値を取り出します。
4行目で、3行目の変数を出力します。
コマンド実行結果
実行すると、powershellの標準出力に「elephant」と出力されます。
また、参考までに「$json.values.properties」を実行した結果は以下の通りです。
PS C:\> $json.values.properties
Number animal location
------ ------ --------
1 {cat, monkey, elephant} {Australia, Japan, China}
PS C:\>
各項目の中に {cat, monkey, elephant} と値が複数あることが確認できます。
拡張子が「.json」のファイルを扱う場合
拡張子が「.json」であっても、拡張子が「.txt」と同じようにして値を取り出すことが可能です。
$Path = "C:\hogehoge\hogehoge.json"
$json = Get-Content $Path | ConvertFrom-Json
[参考] Get-Contentでファイルを読み込んだ場合の挙動
テキストファイルも、JSONファイルも [ConvertFrom-Json] を用いずに [Get-Content] で直接ファイルの内容を読み込むことは可能です。
ですが、Get-Content で直接ファイルの内容を読み込んだ場合、ファイルの中身を文字列として扱うためpowershell上で特定の値を変数に入れることが難しくなります。
※やろうと思えば可能ですが、何文字目から何文字目まで取得する などといった非常にめんどくさいことをしなければなりません。
以下、Get-Content を利用してファイルの内容を読み込んだ場合の実行結果です。
以下で実行しているコマンドは、上記の「実行コマンド」に記載のものとほぼ同じです。
※2行目の「 | ConvertFrom-Json」を除いています。
PS C:\> $Path = "C:\hogehoge\hogehoge.txt"
PS C:\>
PS C:\> $json = Get-Content $Path
PS C:\>
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:\>
「ファイルの中身が文字列として扱われている」という挙動については以下を実行してみるとわかりやすいかと思います。
PS C:\> $aaa = "0123456"
PS C:\>
PS C:\>
PS C:\> $aaa[3] #変数「$aaa」の4文字目の「3」を出力
3
PS C:\>
2.特定の値に対応した項目一覧を抽出する
上記と同じ「hogehoge.txt」を利用します。
以下のPowershellコマンドで、
json形式で記載されたtxtファイル(今回はhogehoge.txt)を読み込み、
その中で、nameが [hoge02] である項目の [propaties] の中にある [animal] に格納されている3つの値を取り出します。
Powershellコマンド
$Path = "C:\hogehoge\hogehoge.txt"
$json = Get-Content $Path | ConvertFrom-Json
$hoge02_p = $json.values | where {$_.name -eq "hoge02"}
$hoge02_p.properties.animal
コマンドの解説
2行目までは先ほどと同じです。
3行目で、[$json] に格納されている「hogehoge.txt」の [values] を読み込みます。
|(パイプ)を利用してその結果を渡し、[where] コマンドを利用して [values] の中にある [name] が [hoge02] と一致するものにソートします。
最後の4行目で、3行目で格納された変数の中から [properties] の中にある [animal] を取り出します。
・3行目と4行目の取り出しイメージ
コマンド実行結果
powershellの標準出力に3つの値(cat02、monkey02、elephant02)が出力されます。
id が [002] に一致する [animal] の3つの値を取り出す
以下のように id の値を指定しても同じ結果を取得することができます。
$Path = "C:\hogehoge\hogehoge02.txt"
$json = Get-Content $Path | ConvertFrom-Json
$hoge02_p = $json.values | where {$_.id -eq "002"}
$hoge02_p.properties.animal
さいごに
私がpowershellを触り始めた時は、[ConvertFrom-Json] というコマンドを知らなかったため、取り出したい値を取り出すことができずに苦戦していました。
ですが、[ConvertFrom-Json] を知ってからは、「取り出したい値を取り出して変数として利用し、後続の処理に渡す」ということを自然とできるようになり、今ではスクリプトなどでかなり活用しています。