🥚やりたいこと
JSONファイルのキー(=プロパティ)だけを別の文字表現に変換したい。
具体的に言うと、例えば、以下のようなJSONファイルがあるとする。
{
"abc": 1,
"def": {
"def_abc": 2,
"def_def": 3
},
"ghi": [
"abc",
"def",
[
{
"ghi_abc": 4
}
]
]
}
上記のJSONファイルを、以下のようにキーのみを大文字にしたり、
{
"ABC": 1,
"DEF": {
"DEF_ABC": 2,
"DEF_DEF": 3
},
"GHI": [
"abc",
"def",
[
{
"GHI_ABC": 4
}
]
]
}
キャメルケースに変換したりしたい。
{
"abc": 1,
"def": {
"defAbc": 2,
"defDef": 3
},
"ghi": [
"abc",
"def",
[
{
"ghiAbc": 4
}
]
]
}
この時に、ちゃんとネストの中のオブジェクト(上記で言うと{"ghi_abc": 4}
のような)のキーもちゃんと変換できるようにするほか、単なるリテラルやリストには変換の影響がないようにしたい。
🐣やってみたこと
以下のようなPythonスクリプトで変換処理を実装してみた。
import json
def convert(data, func=lambda x: x):
if isinstance(data, dict):
obj = {}
for key, value in data.items():
obj[func(key)] = convert(value, func)
return obj
elif isinstance(data, list):
obj = []
for item in data:
obj.append(convert(item, func))
return obj
else:
return data
def to_uppercase(str):
return str.upper()
def to_camelcase(str):
arr = str.split('_')
return arr[0] + ''.join(x.title() for x in arr[1:])
def main():
with open('input.json', 'r') as input_file, open('output.json', 'w') as output_file:
json_obj = json.load(input_file)
converted = convert(json_obj, to_camelcase)
json.dump(converted, output_file)
if __name__ == "__main__":
main()
JSONのキーを再帰的に変換する
def convert(data, func=lambda x: x):
if isinstance(data, dict):
obj = {}
for key, value in data.items():
obj[func(key)] = convert(value, func)
return obj
elif isinstance(data, list):
obj = []
for item in data:
obj.append(convert(item, func))
return obj
else:
return data
この関数でJSONのキーを再帰的に変換している。
最初のif分岐で辞書か配列かそれ以外か判別し、以下のような処理を行う。
- 辞書の場合 ... 辞書内の項目を順に見ていき、それぞれの項目のキーを変換する。値は再帰的にconvertへ引き渡す。
- 配列の場合 ... 配列の項目を順に見ていき、その項目を再帰的にconvertへ引き渡す。
- それ以外 ... そのまま返す。
ちなみに、この実装は以下のように簡潔に書ける。
def convert(data, func=lambda x: x):
if isinstance(data, dict):
return {func(key): convert(value, func) for key, value in data.items()}
elif isinstance(data, list):
return [convert(item, func) for item in data]
else:
return data
実際にキーをどう変換するかの処理は引数のfunc
に委譲している。
🐥まとめ
-
json.load()
で読み込んだJSONファイルをPythonオブジェクトに読み込んだ際、dict/list/その他で判別するだけで問題ないのだろうか。 - 公式ドキュメントの変換表を見る限り問題なさそうだが……。
- パイソニスタのレビュー・マサカリを頂ければ幸いです。