JSONから特定のキーを削除するスクリプト

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 というライブラリが便利そう。

pypi.org

探索するロジック自体は他の要件にも使える。 (特定のオブジェクトに特定のkey, valueを追加したい等)