Python | ファイル操作など:JSON 読み書き

Python
スポンサーリンク

概要(JSON は「辞書やリストをそのまま保存・交換できる」テキスト形式)

JSON は、辞書やリストをそのままテキストにしたようなデータ形式です。Python では標準ライブラリの json モジュールで、追加インストールなしに読み書きできます。重要なのは with 文でファイルを開く、encoding を明示(原則 UTF-8)、そして dump/load を使って“正確に”やり取りすることです。

import json

# 書き込み(ファイルへ保存)
data = {"items": ["coffee", "tea"], "qty": 3}
with open("data.json", "w", encoding="utf-8") as f:
    json.dump(data, f, ensure_ascii=False, indent=2)

# 読み込み(ファイルから取得)
with open("data.json", "r", encoding="utf-8") as f:
    loaded = json.load(f)
Python

基本の読み書き(ここが重要)

ファイルへ書く(json.dump)・文字列へ変換(json.dumps)

dump は「ファイルへ」、dumps は「文字列へ」書き出します。日本語をそのまま保存したいなら ensure_ascii=False、見やすくしたいなら indent を付けます。

import json

data = {"名前": "花子", "qty": 2}
# ファイルへ
with open("user.json", "w", encoding="utf-8") as f:
    json.dump(data, f, ensure_ascii=False, indent=2)

# 文字列へ
s = json.dumps(data, ensure_ascii=False, indent=2)
print(s)
Python

ファイルから読む(json.load)・文字列から変換(json.loads)

load は「ファイルから」、loads は「文字列から」辞書やリストへ変換します。エンコーディングは必ず UTF-8 を明示しましょう。

import json

# ファイルから
with open("user.json", "r", encoding="utf-8") as f:
    user = json.load(f)

# 文字列から
text = '{"name": "coffee", "qty": 2}'
obj = json.loads(text)
Python

型対応と整形オプション(重要ポイントの深掘り)

JSON と Python の型の対応関係

  • JSON object → Python dict
  • JSON array → Python list
  • JSON string → Python str
  • JSON number → Python int/float
  • JSON true/false → Python True/False
  • JSON null → Python None

この対応を前提に、数値や真偽値、null の扱いを意識すると混乱が減ります。

表示や差分に強い整形(indent・sort_keys・separators)

  • indent: 見やすく整形(例:indent=2)
  • sort_keys: キーをソートして書く(差分比較やレビューに便利)
  • separators: 余計なスペースを省いてサイズを小さく
import json

data = {"b": 2, "a": 1}
print(json.dumps(data, ensure_ascii=False, indent=2, sort_keys=True))
Python

日本語の扱い(ensure_ascii=False)

ensure_ascii=True(既定)だと日本語が \uXXXX にエスケープされます。人間が読む前提なら ensure_ascii=False を使いましょう。

json.dumps({"名前": "花子"}, ensure_ascii=False)
Python

そのまま保存できない型への対応(default・object_hook)

datetime や Decimal など「JSONにない型」はそのまま書けません。default で“文字列化のルール”を定義するか、読み込み時は object_hook で“辞書からの復元”を行います。

import json
from datetime import datetime

def encode_default(obj):
    if isinstance(obj, datetime):
        return {"__type__": "datetime", "value": obj.isoformat()}
    raise TypeError

def decode_object(d):
    if d.get("__type__") == "datetime":
        return datetime.fromisoformat(d["value"])
    return d

payload = {"ts": datetime.now()}
s = json.dumps(payload, default=encode_default, ensure_ascii=False)
obj = json.loads(s, object_hook=decode_object)
Python

実務設計と安全策(エンコーディング・Excel 対応・エラー処理)

encoding は原則 UTF-8(必要なら UTF-8-SIG)

日本語を安全に扱うなら UTF-8 が基本。Excel で直接開きたいときは UTF-8-SIG(BOM付き)が有効な場合があります。

import json
with open("excel.json", "w", encoding="utf-8-sig") as f:
    json.dump({"名前": "花子"}, f, ensure_ascii=False, indent=2)
Python

例外処理(JSONDecodeError)

壊れた JSON を読んだときは例外が出ます。ユーザー向けに分かりやすく扱いましょう。

import json

def read_json_safe(path: str):
    try:
        with open(path, "r", encoding="utf-8") as f:
            return json.load(f)
    except FileNotFoundError:
        return None
    except json.JSONDecodeError as e:
        print("JSON の形式が不正です:", e)
        return None
Python

行ごと JSON(NDJSON)で“追記・大規模”に強くする

巨大データや追記ログは、1行に1オブジェクト(NDJSON)にすると扱いやすくなります。

import json

# 追記
with open("events.ndjson", "a", encoding="utf-8") as f:
    f.write(json.dumps({"name": "coffee", "qty": 2}, ensure_ascii=False) + "\n")

# 読み
with open("events.ndjson", "r", encoding="utf-8") as f:
    for line in f:
        evt = json.loads(line)
Python

精度の注意(float の丸め、Decimal 利用)

JSON の number は浮動小数に落ちることがあります。金額などの精度が重要な値は Decimal にパースすると安心です。

import json
from decimal import Decimal

text = '{"price": 1.23}'
obj = json.loads(text, parse_float=Decimal)
Python

例題で身につける(定番から一歩先まで)

例題1:設定ファイルの読み書き(整形・日本語)

import json

def save_config(path: str, cfg: dict) -> None:
    with open(path, "w", encoding="utf-8") as f:
        json.dump(cfg, f, ensure_ascii=False, indent=2, sort_keys=True)

def load_config(path: str) -> dict:
    with open(path, "r", encoding="utf-8") as f:
        return json.load(f)

cfg = {"サイト名": "コーヒー屋", "theme": "dark", "limit": 50}
save_config("config.json", cfg)
print(load_config("config.json"))
Python

例題2:JSON を読みながら型変換・検証

import json

def load_items(path: str) -> list[tuple[str, int]]:
    out: list[tuple[str, int]] = []
    with open(path, "r", encoding="utf-8") as f:
        data = json.load(f)
    for row in data:
        name = row["name"].strip()
        qty = int(row["qty"])
        out.append((name, qty))
    return out
Python

例題3:データの差分比較に強い出力

import json

def export_for_diff(path: str, data: dict) -> None:
    with open(path, "w", encoding="utf-8") as f:
        json.dump(data, f, ensure_ascii=False, indent=2, sort_keys=True)
Python

例題4:NDJSON でログを蓄積し、条件抽出

import json

def append_log(path: str, record: dict) -> None:
    with open(path, "a", encoding="utf-8") as f:
        f.write(json.dumps(record, ensure_ascii=False) + "\n")

def filter_logs(path: str, min_qty: int) -> list[dict]:
    out: list[dict] = []
    with open(path, "r", encoding="utf-8") as f:
        for line in f:
            rec = json.loads(line)
            if int(rec.get("qty", 0)) >= min_qty:
                out.append(rec)
    return out
Python

まとめ

JSON は「辞書・リストをテキストで安全にやり取り」するための標準形式。Python では json.dump/load(ファイル)、json.dumps/loads(文字列)を使い、UTF-8 を明示、ensure_ascii=False で日本語を保ち、indent/sort_keys で読みやすく。JSON にない型は default/object_hook で変換し、精度が要る数値は Decimal を活用。大規模や追記用途は NDJSON を選べば運用が楽になります。この基本線を押さえるだけで、初心者でも正確・堅牢な JSON 読み書きが短いコードで書けます。

タイトルとURLをコピーしました