PowerShell 2.0で使えるシンプルなConvertTo-Jsonの作成

PowerShellを使っていて、他の言語やAPIと連携させようとすると、データ形式が大事になってきます。
XMLでもCSVでも何でもいいのですが、オブジェクトを書くのならばやっぱりJSONが扱いやすいですね。

標準のコマンドレットでは、PSオブジェクトからJSON文字列を作成するConvertTo-Jsonや、
その逆のConvertFrom-Jsonがあります。癖はありますが、一通りの機能が揃っています。

が、それはPowerShell 3.0以降の話。つまりはWindows 7やらWindows Server 2008R2あたりではまだ標準搭載されていないということです。PowerShell (というかWMF)をバージョンアップする手もありますが、今回は素のPowerShell 2.0で行けるところまでやってみたいと思います。

もくじ:

はじめに

PowerShellはWindows APIや.NETの機能を使う分には便利なのですが、さすがに単体で規模の大きなソフトウェアを作るのは力不足。
ということで、せめてJSON形式の文字列にして保存しておけば他のプログラムで読めるはず。

PowerShell 3.0以降であればConvertTo-JsonでJSON文字列が生成できるので、これをそのまま書き出せば大丈夫。
-Depthパラメータを充分な大きさに指定しないと展開されないのが罠っぽいですね
コンパクト版(-Compressパラメータあり)なら、スキルの乏しい私にもオブジェクトを解析して何とか作れそうです。

環境はWindows10 + Python 3.6、PowerShellはVersion 5ですが、上記の例と同じくバージョンを2に指定して動作を確認しています。

シンプルなConvertTo-Jsonを作成する

まずはサンプルを掲載しておきます。前半部分はオブジェクトからJSON文字列を組み立てる関数、後半部分はそれを使ったテスト用の記載です。うーん、何とも突貫な感じ。。。

以下にポイントをメモしておきます。

ConvertTo-Json_Alt関数

要するに、オブジェクトの要素を辿って、カッコで括れれば良いのです。
メンバの型で条件分岐させ、値ならば整形し、配列(array)または連想配列(hashtable)なら再帰的に処理します。JSONの仕様では文字列・数値・論理値・NULL値を扱えればいいはず。

ちょっとややこしいのは$null(NULL型)の判定。配列が非NULLを含んでいても真に判定されてしまうので、配列をフィルタしています。

標準の<ConvertTo-JsonはJScriptを内部的に呼び出しているようなので、おそらく.NETのAPIを使っても同じようなことができるような気がします。まあ厳密なものを作りたいわけではないので、動けば良し。

JSONファイルへの保存

後でPython (3.x系)に渡したいので、UTF-8で保存しておきます。パイプでOut-Fileに渡し、-Encodingオプションを指定します。

PowerShellで実行するとこんな感じ。ずらずら出力されて読みにくいですが、たぶんエンコードされているはず。
返り値が文字型(String)なので、Rest APIを使うときはこのままInvoke-RestMethodコマンドレットなどに渡せます。

Pythonへのインポート

ここではPowerShellで出力したJSON文字列ファイルを、Pythonへインポートしてオブジェクトへ変換する処理のサンプルを記載します。
標準のjsonモジュールで読めるはずですが、おそらくこのスクリプトはPython 2系統で動きません。

以下、上と同様にポイントを書いておきます。

JSONファイルの読み込み

やや扱いが面倒なのは、Windows処理系にありがちなBOM付きテキストファイルですね。文字コードをうまく指定しないと、文字化けするかデコードエラーが発生します。

Python 2系統では試していませんが、おそらく同様にcodecsモジュールで文字コードを指定すれば動くと思われます。

JSONファイルの書き出し

逆にファイルへ書き出す時もBOM付きUTF-8を指定すると、PowerShellなどWindows系の環境で扱いやすくなるでしょう。
日本語を含む場合を想定してensure_asciiを指定しておきます。

前述のスクリプトを実行すると、"data.json"ファイルを読み込み、Pythonオブジェクトとして解釈します。インデント付きで表示させて分かる通り、期待通りにJSONファイルを作成できているようですね。