【Python標準ライブラリ入門 第3回】データ交換の標準!jsonモジュールでJSONを自由自在に扱おう

「プログラムの設定をファイルに保存しておきたいけど、どうすればいい?」
「Web APIから送られてくるデータって、よくJSON形式って聞くけど何だろう?」
「Pythonの辞書やリストを、他のプログラムでも使える形でやり取りしたい!」

こんにちは! Python標準ライブラリ探検隊、隊長のPythonistaです! 前回はrandomモジュールでプログラムに偶然性をもたらす方法を学びましたね。プログラムに動きが出て面白くなったのではないでしょうか。

シリーズ第3回の今回は、現代のプログラミング、特にWeb連携や異なるシステム間でのデータ交換において欠かせない存在となっているJSON(ジェイソン)形式と、それをPythonで扱うための標準ライブラリjsonモジュールを徹底解説します! このモジュールを使えば、Pythonのデータ構造(主に辞書やリスト)をJSON形式の文字列やファイルに変換したり、逆にJSON形式のデータをPythonのデータ構造として読み込んだりすることが驚くほど簡単にできます。設定ファイルの管理からAPI連携まで、jsonモジュールはあなたのPythonプログラミングの幅を大きく広げてくれますよ!その他の投稿はこちら


1. JSONとは? なぜデータ交換でこんなによく使われるの?

まずは、jsonモジュールが扱う「JSON」そのものについて理解を深めましょう。

1.1. JSON (JavaScript Object Notation) の概要

JSON (ジェイソン / JavaScript Object Notation) は、軽量なデータ交換フォーマットの一つです。その名前の通り、元々はJavaScriptのオブジェクトリテラルの書式をベースにしていますが、人間にも読み書きしやすく、かつコンピュータにとっても解釈しやすいシンプルな構造のため、現在ではJavaScriptに限らず非常に多くのプログラミング言語で標準的に利用されています。

JSONは主に以下の要素で構成されます。

  • オブジェクト (Object): 名前(キー、必ずダブルクォートで囲まれた文字列)と値のペアを波括弧{}で囲んだもの。Pythonの辞書に似ています。
    例: { "name": "山田太郎", "age": 30, "isStudent": false }
  • 配列 (Array): 値の順序付きリストを角括弧[]で囲んだもの。Pythonのリストに似ています。
    例: [ "リンゴ", "バナナ", "ミカン" ]
  • 値 (Value): 上記のオブジェクトや配列の他に、以下の基本的なデータ型があります。
    • 文字列 (String): ダブルクォート""で囲まれたテキスト。 (例: "こんにちは")
    • 数値 (Number): 整数または浮動小数点数。 (例: 100, 3.14, -50)
    • 真偽値 (Boolean): true または false。 (小文字であることに注意)
    • null: 何もないことを表す特別な値。PythonのNoneに相当します。

これらの要素を組み合わせて、複雑なデータ構造も表現できます。

1.2. JSONがデータ交換でよく使われる理由

  • 人間にとって読み書きしやすい (Human-readable): テキストベースで構造もシンプルなため、開発者が内容を直接確認したり、手で編集したりすることが比較的容易です。
  • 軽量である (Lightweight): XMLなど他のデータ交換フォーマットと比較して、一般的に冗長性が少なく、データサイズが小さくなる傾向があります。通信量やストレージ容量の節約に繋がります。
  • 多くのプログラミング言語でサポートされている: Python、JavaScript、Java、C#、PHP、Rubyなど、主要なプログラミング言語のほとんどがJSONを扱うためのライブラリや機能を標準または簡単に利用できる形で提供しています。これにより、異なる言語で書かれたシステム間でのデータ交換がスムーズに行えます。
  • Webとの親和性が高い: 元々JavaScriptとの相性が良いため、Webブラウザとサーバー間の通信(特に非同期通信であるAjaxや、Web APIのレスポンス形式)で広く採用されています。

2. Pythonのjsonモジュール:基本的な使い方

PythonでJSONデータを扱うには、標準ライブラリであるjsonモジュールをインポートします。

import json

2.1. PythonのデータをJSON文字列に変換(シリアライズ)

Pythonの辞書やリストなどのオブジェクトをJSON形式の文字列に変換する処理をシリアライズ (Serialization) と言います。jsonモジュールでは、dumps()メソッド(dump stringの略)を使います。

json.dumps(python_object, indent=None, ensure_ascii=True, sort_keys=False)

  • python_object: JSON文字列に変換したいPythonオブジェクト。
  • indent (オプション): JSON文字列を見やすくインデント(字下げ)する際のスペース数を整数で指定します。指定しない場合は1行の文字列になります。
  • ensure_ascii (オプション): デフォルトはTrueで、非ASCII文字(日本語など)は\uXXXXのような形にエスケープされます。Falseに設定すると、日本語などの文字がそのまま出力されます(UTF-8エンコーディングの環境で有効)。
  • sort_keys (オプション): デフォルトはFalseです。Trueに設定すると、辞書のキーをアルファベット順(辞書順)にソートして出力します。

サンプルコード:

import json

# Pythonの辞書データ
data_dict = {
    "name": "佐藤花子",
    "age": 28,
    "city": "東京",
    "hobbies": ["読書", "映画鑑賞"],
    "is_programmer": True
}

# Pythonの辞書をJSON文字列に変換 (インデントなし)
json_string_no_indent = json.dumps(data_dict, ensure_ascii=False)
print(f"\n--- インデントなしJSON文字列 ---")
print(json_string_no_indent)

# Pythonの辞書をJSON文字列に変換 (インデントあり、日本語そのまま)
json_string_with_indent = json.dumps(data_dict, indent=4, ensure_ascii=False, sort_keys=True)
print(f"\n--- インデント・日本語表示・キーソートありJSON文字列 ---")
print(json_string_with_indent)

実行結果 (例):

--- インデントなしJSON文字列 ---
{"name": "佐藤花子", "age": 28, "city": "東京", "hobbies": ["読書", "映画鑑賞"], "is_programmer": true}

--- インデント・日本語表示・キーソートありJSON文字列 ---
{
    "age": 28,
    "city": "東京",
    "hobbies": [
        "読書",
        "映画鑑賞"
    ],
    "is_programmer": true,
    "name": "佐藤花子"
}

2.2. JSON文字列をPythonのデータに変換(デシリアライズ)

JSON形式の文字列をPythonの辞書やリストなどのオブジェクトに変換する処理をデシリアライズ (Deserialization) と言います。jsonモジュールでは、loads()メソッド(load stringの略)を使います。

json.loads(json_string)

  • json_string: Pythonオブジェクトに変換したいJSON形式の文字列。

サンプルコード:

import json

json_data_str = '{"name": "鈴木一郎", "age": 35, "email": "suzuki@example.com", "active": true, "scores": [80, 95, 77]}'

# JSON文字列をPythonの辞書に変換
python_dict = json.loads(json_data_str)

print(f"\n--- JSON文字列から変換したPython辞書 ---")
print(python_dict)
print(f"名前: {python_dict['name']}")
print(f"年齢: {python_dict['age']}")
print(f"スコアの最初の値: {python_dict['scores'][0]}")
print(f"型: {type(python_dict)}")
print(f"scoresの型: {type(python_dict['scores'])}")

実行結果 (例):

--- JSON文字列から変換したPython辞書 ---
{'name': '鈴木一郎', 'age': 35, 'email': 'suzuki@example.com', 'active': True, 'scores': [80, 95, 77]}
名前: 鈴木一郎
年齢: 35
スコアの最初の値: 80
型: <class 'dict'>
scoresの型: <class 'list'>

JSONのオブジェクトはPythonの辞書(dict)に、JSONの配列はPythonのリスト(list)に、true/falseTrue/Falseに、nullNoneに変換されていることが分かります。


3. JSONファイルを使ったデータの読み書き

プログラムの設定や、処理結果のデータをファイルとして保存・読み込みする際にJSON形式は非常に便利です。jsonモジュールは、ファイル操作と組み合わせるためのメソッドも提供しています。

3.1. PythonのデータをJSONファイルに書き出す(保存)

PythonのオブジェクトをJSON形式でファイルに書き出すには、json.dump()メソッド(dumpの略)を使います。dumps()と似ていますが、こちらは文字列ではなくファイルオブジェクトを扱います。

json.dump(python_object, file_object, indent=None, ensure_ascii=True, sort_keys=False)

  • python_object: ファイルに書き出したいPythonオブジェクト。
  • file_object: 書き込みモード ('w') で開いたファイルオブジェクト。
  • indent, ensure_ascii, sort_keys: dumps()と同じです。

ファイルを扱う際は、with open(...) as f:構文を使うと、ファイルのクローズ処理を忘れずに行えるため安全で推奨されます。また、日本語などのマルチバイト文字を扱う場合は、open()関数で文字エンコーディング(通常は'utf-8')を指定することが重要です。

サンプルコード:

import json

settings_data = {
    "user_name": "PythonistaJP",
    "theme": "dark",
    "notifications": {
        "email": True,
        "sms": False
    },
    "languages": ["Python", "JavaScript"]
}

file_path = 'settings.json'

# Pythonの辞書をJSONファイルに書き出す
try:
    with open(file_path, 'w', encoding='utf-8') as f:
        json.dump(settings_data, f, indent=4, ensure_ascii=False)
    print(f"\nデータが '{file_path}' に保存されました。")
except IOError as e:
    print(f"ファイル書き込みエラー: {e}")

# settings.json の中身 (例):
# {
#     "user_name": "PythonistaJP",
#     "theme": "dark",
#     "notifications": {
#         "email": true,
#         "sms": false
#     },
#     "languages": [
#         "Python",
#         "JavaScript"
#     ]
# }

3.2. JSONファイルからPythonのデータを読み込む

JSONファイルからデータを読み込み、Pythonオブジェクトに変換するには、json.load()メソッド(loadの略)を使います。

json.load(file_object)

  • file_object: 読み込みモード ('r') で開いたファイルオブジェクト。

サンプルコード (上記で保存したsettings.jsonを読み込む):

import json

file_path = 'settings.json' # 上記で保存したファイル

# JSONファイルからデータを読み込む
try:
    with open(file_path, 'r', encoding='utf-8') as f:
        loaded_settings = json.load(f)
    
    print(f"\n'{file_path}' から読み込んだデータ:")
    print(loaded_settings)
    print(f"ユーザー名: {loaded_settings['user_name']}")
    print(f"Email通知: {loaded_settings['notifications']['email']}")
except FileNotFoundError:
    print(f"エラー: ファイル '{file_path}' が見つかりません。")
except json.JSONDecodeError:
    print(f"エラー: ファイル '{file_path}' は正しいJSON形式ではありません。")
except IOError as e:
    print(f"ファイル読み込みエラー: {e}")

ここでは、ファイルが見つからない場合 (FileNotFoundError) や、JSONの形式が正しくない場合 (json.JSONDecodeError) のための簡単なエラーハンドリングも加えています。


4. jsonモジュールで扱う際の注意点

  • キーは常に文字列: JSONオブジェクトのキーは必ず文字列でなければなりません。Pythonの辞書では数値などもキーにできますが、JSONにシリアライズする際には文字列に変換されるか、エラーになる場合があります(json.dumpsskipkeys=Trueでスキップも可能ですが、通常は文字列キーを推奨)。
  • 対応するデータ型:
    • Pythonのdict ↔ JSONのオブジェクト
    • Pythonのlist, tuple ↔ JSONの配列
    • Pythonのstr ↔ JSONの文字列
    • Pythonのint, float ↔ JSONの数値
    • PythonのTrue/False ↔ JSONのtrue/false (小文字)
    • PythonのNone ↔ JSONのnull (小文字)
  • 直接変換できないPythonの型: Pythonのset型や、datetimeオブジェクト、自作クラスのインスタンスなどは、そのままでは直接JSONにシリアライズできません。これらをJSONにするには、事前に文字列や数値、あるいはJSONで表現可能な辞書やリストの形に変換する処理が必要です。(より高度な方法として、カスタムエンコーダ/デコーダを作成することも可能です。)

5. 実践的な例:ToDoリストをJSONファイルで管理

簡単なToDoリスト(タスクのリスト)をJSONファイルに保存し、読み込む例を見てみましょう。

import json

TODO_FILE = 'todolist.json'

def load_todos():
    """ToDoリストをファイルから読み込む"""
    try:
        with open(TODO_FILE, 'r', encoding='utf-8') as f:
            todos = json.load(f)
    except FileNotFoundError:
        todos = [] # ファイルがなければ空のリストで開始
    return todos

def save_todos(todos):
    """ToDoリストをファイルに保存する"""
    with open(TODO_FILE, 'w', encoding='utf-8') as f:
        json.dump(todos, f, indent=4, ensure_ascii=False)
    print("ToDoリストを保存しました。")

def add_todo(todos, task_description):
    """ToDoアイテムを追加する"""
    # 各タスクを辞書として表現(完了状態も持つ)
    task = {"description": task_description, "done": False}
    todos.append(task)
    print(f"タスク「{task_description}」を追加しました。")

def show_todos(todos):
    """ToDoリストを表示する"""
    if not todos:
        print("ToDoリストは空です。")
        return
    print("\n--- ToDoリスト ---")
    for i, task_item in enumerate(todos, 1):
        status = "[完了]" if task_item["done"] else "[未完了]"
        print(f"{i}. {status} {task_item['description']}")
    print("------------------")

# メイン処理
my_todos = load_todos() # 起動時にToDoを読み込み
show_todos(my_todos)

add_todo(my_todos, "Pythonの勉強をする")
add_todo(my_todos, "牛乳を買う")
show_todos(my_todos)

# 最初のタスクを完了にする (例)
if my_todos:
    my_todos[0]["done"] = True
show_todos(my_todos)

save_todos(my_todos) # 終了前にToDoを保存

このプログラムを実行すると、todolist.jsonというファイルにToDoリストが保存され、次回実行時にはその内容が読み込まれます。


まとめ:jsonモジュールでデータ連携をもっと身近に!

今回は、Pythonの標準ライブラリ解説シリーズ第3回として、jsonモジュールの基本的な使い方を学びました。

  • JSON形式の基本構造(オブジェクト、配列、各種データ型)。
  • PythonオブジェクトとJSON文字列の相互変換(シリアライズjson.dumps()、デシリアライズjson.loads())。
  • PythonオブジェクトとJSONファイルの相互変換(書き出しjson.dump()、読み込みjson.load())。
  • 日本語を扱う際のensure_ascii=Falseや、整形のためのindent引数。

jsonモジュールは、設定ファイルの管理、簡単なデータの永続化、そして特にWeb APIを介した他のシステムとのデータ連携など、現代のプログラミングにおいて非常に広範囲で活用されています。この基本をマスターすることで、あなたのPythonプログラムが外部の世界と繋がり、より多くのことができるようになるでしょう。

標準ライブラリにはまだまだ便利なモジュールがたくさんあります。次回もPythonの強力な道具箱の中身を一緒に見ていきましょう!お楽しみに!

【Python標準ライブラリ入門 第4回】ファイル・ディレクトリ操作の達人になろう!osモジュール徹底ガイド

その他の投稿はこちら


コメント

このブログの人気の投稿

タイトルまとめ

これで迷わない!WindowsでPython環境構築する一番やさしい方法 #0

【Python標準ライブラリ完結!】11の冒険をありがとう!君のPython力が飛躍する「次の一歩」とは? 🚀