読み込んだjsonファイルのデータ形式が意図したものになっているのかを検証したいときがある。
画像認識屋といえども、jsonファイルを避けていくことができない。
主旨:
jsonファイルのデータ形式の確認にDictを使って、制御構文を簡単にし、見通しを改善しようという話
おかれている状況
- 該当のjsonファイルの詳細な設計仕様書はなく、個別のファイルがあるだけ
- jsonファイルの中のデータ形式は、入れ子になったDict型, List型を含む。
- keyの種類によって値の型が異なる。
- keyの種類によって値の範囲の確認が必要。
やりがちなこと
- keyの種類によって値の型が異なるので、次のようなコードを書いてしまう。
for k, v in d.items():
if k == "name":
assert isinstance(v, str)
elif k == "age":
assert isinstance(v, float)
else:
print(f"unexpected key")
こういうのが増えてしまうと、
元のDict型dとの対応関係が保たれているのかが、しだいにわかりにくくなってしまう。
とくに、データ形式が多重に入れ子になっていると、このようなコードが複雑過ぎて、元のデータ形式と対応がとれているのかがわからなくなってしまう。
対策案:
各キーによって、どのような確認動作をするのが変わる。
確認動作を関数にまとめる。
ACTIONS = {キー: そのキーに対応する値での確認動作の関数}
となるようなDict型を用意する。
そうすると
for k, v in d.items():
assert ACTIONS[k](v)
ような記述が簡単になる。
このように記述すれば、制御構文が不必要に複雑になりすぎるのを防げる。
そして、動作の記述が足りているのかどうかは
ACTIONS というデータ形式の定義の確認で判断できる。
付記:
実は、jsonファイルの読み込みのデータ形式の確認にはもっといい方法がある。
pythonのclassをjsonファイルとして出力したり、jsonファイルを読み込んでclassのインスタンスをすることだ。
選択肢1: dataclasses_json
dataclasses_json を使うことです。
pip instal dataclasses_json
pythonの標準ライブラリにある@dataclassのデコレータを使ったうえで
@dataclasses_json のデコレータも合わせて使います。
そのような使い方は、記事があるので参照してください。
dataclass_jsonを利用したJSONとPythonオブジェクトの相互変換
選択肢2: pydantic
どちらにしても、自前のコードの行が少なくなるので、保守性がよくなるはずです。
pydantic の素晴らしいところ
from pydantic import BaseModel
class Something(BaseModel):
のようにpydanticを利用してclassを定義すると、
それを使うことで、インスタンスから辞書形式の生成、辞書形式からインスタンスの生成ができるという点です。
このため、それらの手法が標準化されます。
ユーザーが自分で書かなければならないコードが少なくなります。
付記2:
自作アプリケーションの設定ファイルのデータ形式を選択する際に
- jsonファイル
- toml ファイル
- yaml ファイル
などが候補になるだろう。