Overview
同僚が大量のJSONテストデータを手作業で編集するのが辛いと言っていたときに書いた。
Usage
yoshiki@yoshiki-mbp:python/script ‹main*›$ cat ./test_data/data_remove.json { "key": "value", "remove_target1": "value", "object": { "key": "value", "remove_target2": "value" } } yoshiki@yoshiki-mbp:python/script ‹main*›$ python remove_keys_from_json_file.py ./test_data/data_remove.json { "key": "value", "object": { "key": "value" } }
Script
REMOVE_ITEM_LIST
に消したいキーのリストをハードコードしている。引数にすることもできるが、特定のタスクでしか使わないのと連続実行することが多い(しないなら手作業で十分)なので、このままにしている。- 指定したキーがネストしたオブジェクトの中にあっても削除される。(上の例の
remove_target2
) - 簡単なロジック説明
- 対象がリストだったら中のオブジェクトを探索する
- 対象がオブジェクトだったら削除対象チェック+中のオブジェクトとリストを探索する
remove_keys_from_json_file.py
import json from collections import OrderedDict import sys REMOVE_ITEM_LIST = ["remove_target1", "remove_target2"] def remove_fields(arg): if isinstance(arg, list): for item in arg: remove_fields(item) elif isinstance(arg, dict): for remove_item in REMOVE_ITEM_LIST: if remove_item in arg: del(arg[remove_item]) for value in arg.values(): remove_fields(value) if __name__ == '__main__': args = sys.argv path = args[1] with open(path) as f: od = json.load(f, object_pairs_hook=OrderedDict) remove_fields(od) print(json.dumps(od, indent=2, ensure_ascii=False))
Enhance
対象のキー名が十分にユニークなものだったのでこれで上手くいった。
間違ったものを削除しないようにするためにはJSON path (e.g. $.object.remove_target2
) で指定できるようにする方法が考えられる。
jsonpath-python
というライブラリが便利そう。
探索するロジック自体は他の要件にも使える。 (特定のオブジェクトに特定のkey, valueを追加したい等)