概要
JSONファイルから指定のエントリを抽出し、かつ、他のエントリ内の指定のプロパティと一致する場合はそのエントリ内の値も一緒に取得する方法を、備忘録も兼ねて記載します。
(文章だと意図が伝わりづらいので、サンプルコードを...)
サンプルコード解説
以下のようなJSONがあるとします。
サンプルなのでわかりやすいようにしていますが、実際は支店(branch
)も製品(product_code
)もたくさんある前提です。
001_sample_response.json
{
"response": {
"status": "0000",
"company_code": "12345",
"branch": {
"tokyo": [
{
"product_code": "001",
"unit_price": "100",
"quantity": "10",
"sales_amount": "1000",
"tokyo_status": "Tokyo、達成です!"
},
{
"product_code": "002",
"unit_price": "200",
"quantity": "1",
"sales_amount": "200",
"tokyo_status": "Tokyo、未達です!"
}
],
"osaka": [
{
"product_code": "001",
"unit_price": "100",
"quantity": "2",
"sales_amount": "200",
"osaka_status": "Osaka、未達です!"
},
{
"product_code": "002",
"unit_price": "200",
"quantity": "5",
"sales_amount": "1000",
"osaka_status": "Osaka、達成です!"
}
]
}
}
}
上記から、大阪支店の情報(osaka
エントリ全体)を抽出し、かつ、プロパティのproduct_code
とunit_price
の両方が一致する東京支社のステータスを取り出すコードを紹介します。今回は001
から100
まである想定なのでrange
でループを作成しています。
import os
import json
# 出力ディレクトリを作成
output_dir = "./sample_osaka_files"
if not os.path.exists(output_dir):
os.makedirs(output_dir)
for i in range(1, 100):
json_file_path = f"./sample_json_files/{str(i).zfill(3)}_sample_response.json"
output_file_path = f"{output_dir}/{str(i).zfill(3)}_osaka.json"
try:
with open(json_file_path, "r", encoding="utf-8") as json_file:
data = json.load(json_file)
if "response" in data and "branch" in data["response"]:
branch = data["response"]["branch"]
if "tokyo" in branch and "osaka" in branch:
tokyo_branch = branch["tokyo"]
osaka_branch = branch["osaka"]
entries_with_status = []
for osaka in osaka_branch:
osaka_factors = (
osaka.get("product_code"),
osaka.get("unit_price")
)
for tokyo in tokyo_branch:
tokyo_factors = (
tokyo.get("product_code"),
tokyo.get("unit_price")
)
if osaka_factors == tokyo_factors:
osaka["tokyo_status"] = tokyo.get("tokyo_status")
entries_with_status.append(osaka)
break
if entries_with_status:
entries_with_status.insert(0, {"branch": "osaka"})
with open(output_file_path, "w", encoding="utf-8") as output_file:
json.dump(entries_with_status, output_file, ensure_ascii=False, indent=4)
except (FileNotFoundError, json.JSONDecodeError) as e:
print(f"処理エラー: {json_file_path} - {e}")
実行結果は以下になります。
例えばproduct_code
が001
&unit_price
が100
の製品の場合、大阪支店の情報(quantity
やsales_amount
)を抽出しつつ、同じくproduct_code
が001
&unit_price
が100
である東京支店のステータスも取得できます。
001_osaka.json
[
{
"branch": "osaka"
},
{
"product_code": "001",
"unit_price": "100",
"quantity": "2",
"sales_amount": "200",
"osaka_status": "Osaka、未達です!",
"tokyo_status": "Tokyo、達成です!"
},
{
"product_code": "002",
"unit_price": "200",
"quantity": "5",
"sales_amount": "1000",
"osaka_status": "Osaka、達成です!",
"tokyo_status": "Tokyo、未達です!"
}
]
ネストがかなり深く力技のコーディングですが、これで作業すると100件とか整理する必要がある場合は非常に楽でした。