json版sedことjqのPythonバインディングをcythonで作った
jqはjsonデータを加工するコマンド、「json界のsed」と呼ばれています。
- jq is a lightweight and flexible command-line JSON processor.
- jqコマンドでjsonデータを整形・絞り込み - Qiita [キータ]
- JSONを超絶に読みやすくする jq コマンド - WebAPIバリバリ使うor開発する人必須
- 軽量JSONパーサー『jq』のドキュメント:『jq Manual』をざっくり日本語訳してみました | Developers.IO
手軽さで知られるjqですが、実はjqのスクリプトにはmap・filterなどの強力なビルドイン関数があり、 変数・関数を定義できるなど、強力なデータ操作能力を持っています。しかもコンパクト。
文字列に対する正規表現のようなパワフルさです。
こんな強力な能力を、JSONだけに閉じ込めておくのは勿体無い!そこで!
東北の中山間地にある実家で強制ネット断食だった三ガ日に、Pythonバインディングをcythonで作ってみた!
pyjq: Binding for jq JSON Processor
インストール
事前にjqをとってきてコンパイルしておきます。
# 依存ライブラリ
# debian系の場合
sudo apt-get install flex bison gcc make autoconf
git clone https://github.com/stedolan/jq
cd jq
git checkout jq-1.3
autoreconf -i
./configure
make
sudo make install
# ダイナミックリンクライブラリのキャッシュを更新
# Linuxの場合
ldconfig
あとはpipでインストールできます。pyjq自体のコンパイルはすぐなのですが、cythonのコンパイルに少し時間がかかります。
pip install pyjq
サンプル
数値・文字列・真偽値・リスト・辞書でできたデータ構造を、jqスクリプトで直接処理できます。
戻り値はjson(文字列)ではなく、データ構造が帰ってきます。
>>> data = dict(
... parameters= [
... dict(name="PKG_TAG_NAME", value="trunk"),
... dict(name="GIT_COMMIT", value="master"),
... dict(name="TRIGGERED_JOB", value="trunk-buildall")
... ],
... id="2013-12-27_00-09-37",
... changeSet=dict(items=[], kind="git"),
... )
>>> import pyjq
>>> pyjq.first('.parameters[] | {"param_name": .name, "param_type":.type}', data)
{'param_type': None, 'param_name': 'PKG_TAG_NAME'}
関数は3種類あります。
apply(script, value, **kw)
- jqの出力した値をリストで返す
first(script, value, default=None, **kw)
- jqの出力した値の最初のものを返す
one(script, value, **kw)
- jqが値を1つだけ返した時、その値を返す。 値を出力しなかったり2つ以上の値を返したときは、例外を投げる。
また、スクリプトを固めて使いまわすためのpyjq.compile
もあります(正規表現のre.compile
のように)。
制限
jqはjson用のコマンドなので、pyjq
もjsonに変換可能なデータ構造(数値・文字列・真偽値・リスト・辞書だけを含むデータ構造)しか処理できません。
まあ、これで十分な気もしますが、どうなんでしょう?