← ブログに戻る

PythonとJSON:完全ガイド

PythonでJSONを扱う方法を学びます。読み取り、書き込み、パース、シリアライズ、エラー処理、ベストプラクティス。

Big JSON Team13 分で読めますprogramming
B

Big JSON Team

Technical Writer

Expert in JSON data manipulation, API development, and web technologies. Passionate about creating tools that make developers' lives easier.

13 分読む

# PythonとJSON:完全ガイド

Pythonには強力な組み込みJSONサポートがあり、JSONデータの操作が簡単です。

jsonモジュール

Pythonのjsonモジュールは、JSONデータを扱うための標準ライブラリです。

インポート

import json

JSONの読み取り

文字列からのパース

import json

# JSON文字列

json_string = '{"name": "田中太郎", "age": 30, "city": "東京"}'

# Pythonオブジェクトに変換

data = json.loads(json_string)

print(data['name']) # 田中太郎

print(data['age']) # 30

print(type(data)) # <class 'dict'>

ファイルからの読み取り

import json

# JSONファイルを読み取り

with open('data.json', 'r', encoding='utf-8') as file:

data = json.load(file)

print(data)

例:user.json

{

"name": "田中太郎",

"age": 30,

"email": "tanaka@example.com",

"hobbies": ["読書", "旅行", "料理"]

}

with open('user.json', 'r', encoding='utf-8') as f:

user = json.load(f)

print(f"名前: {user['name']}")

print(f"趣味: {', '.join(user['hobbies'])}")

JSONの書き込み

オブジェクトから文字列へ

import json

# Python辞書

user = {

"name": "田中太郎",

"age": 30,

"city": "東京",

"active": True,

"balance": None

}

# JSON文字列に変換

json_string = json.dumps(user, ensure_ascii=False)

print(json_string)

# {"name": "田中太郎", "age": 30, "city": "東京", "active": true, "balance": null}

フォーマットされた出力

# インデント付き

json_string = json.dumps(user, indent=2, ensure_ascii=False)

print(json_string)

# {

# "name": "田中太郎",

# "age": 30,

# "city": "東京",

# "active": true,

# "balance": null

# }

ファイルへの書き込み

import json

user = {

"name": "田中太郎",

"age": 30,

"email": "tanaka@example.com"

}

# ファイルに書き込み

with open('output.json', 'w', encoding='utf-8') as f:

json.dump(user, f, indent=2, ensure_ascii=False)

データ型マッピング

Python → JSON

| Python | JSON |

|--------|------|

| dict | object |

| list, tuple | array |

| str | string |

| int, float | number |

| True | true |

| False | false |

| None | null |

JSON → Python

| JSON | Python |

|------|--------|

| object | dict |

| array | list |

| string | str |

| number (int) | int |

| number (real) | float |

| true | True |

| false | False |

| null | None |

import json

# Pythonデータ

data = {

"string": "こんにちは",

"number": 42,

"float": 3.14,

"boolean": True,

"null_value": None,

"list": [1, 2, 3],

"nested": {

"key": "value"

}

}

# JSON変換

json_str = json.dumps(data, ensure_ascii=False)

print(json_str)

# 逆変換

parsed = json.loads(json_str)

print(type(parsed['boolean'])) # <class 'bool'>

詳細設定

ensure_ascii

# ensure_ascii=True(デフォルト)

json.dumps({"name": "田中"})

# '{"name": "\u7530\u4e2d"}'

# ensure_ascii=False

json.dumps({"name": "田中"}, ensure_ascii=False)

# '{"name": "田中"}'

sort_keys

data = {"c": 3, "a": 1, "b": 2}

# キーをソート

json.dumps(data, sort_keys=True)

# '{"a": 1, "b": 2, "c": 3}'

indent

data = {"name": "田中", "age": 30}

# インデント2

print(json.dumps(data, indent=2, ensure_ascii=False))

# {

# "name": "田中",

# "age": 30

# }

# インデント4

print(json.dumps(data, indent=4, ensure_ascii=False))

separators

# コンパクト出力

json.dumps(data, separators=(',', ':'))

# '{"name":"田中","age":30}'

# 読みやすい出力

json.dumps(data, separators=(', ', ': '))

# '{"name": "田中", "age": 30}'

カスタムエンコーディング

カスタムクラスのシリアライズ

import json

from datetime import datetime

class User:

def __init__(self, name, age, created):

self.name = name

self.age = age

self.created = created

# カスタムエンコーダー

class UserEncoder(json.JSONEncoder):

def default(self, obj):

if isinstance(obj, User):

return {

'name': obj.name,

'age': obj.age,

'created': obj.created.isoformat()

}

if isinstance(obj, datetime):

return obj.isoformat()

return super().default(obj)

# 使用

user = User("田中太郎", 30, datetime.now())

json_str = json.dumps(user, cls=UserEncoder, ensure_ascii=False)

print(json_str)

default関数を使用

from datetime import datetime

def json_serial(obj):

"""JSON serializer for objects not serializable by default"""

if isinstance(obj, datetime):

return obj.isoformat()

raise TypeError(f"Type {type(obj)} not serializable")

data = {

"name": "田中太郎",

"created": datetime.now()

}

json_str = json.dumps(data, default=json_serial, ensure_ascii=False)

カスタムデコーディング

object_hook

import json

from datetime import datetime

def decode_user(dct):

if 'created' in dct:

dct['created'] = datetime.fromisoformat(dct['created'])

return dct

json_str = '{"name": "田中太郎", "created": "2026-01-16T10:00:00"}'

data = json.loads(json_str, object_hook=decode_user)

print(type(data['created'])) # <class 'datetime.datetime'>

エラー処理

JSONDecodeError

import json

invalid_json = '{"name": "田中太郎", "age": 30,}' # 末尾のカンマ

try:

data = json.loads(invalid_json)

except json.JSONDecodeError as e:

print(f"JSONエラー: {e.msg}")

print(f"行: {e.lineno}, 列: {e.colno}")

print(f"位置: {e.pos}")

安全なパース

def safe_json_loads(json_str, default=None):

"""安全にJSONをパース"""

try:

return json.loads(json_str)

except json.JSONDecodeError as e:

print(f"JSONパースエラー: {e}")

return default

except Exception as e:

print(f"予期しないエラー: {e}")

return default

# 使用

result = safe_json_loads('invalid json', default={})

大きなJSONファイル

ストリーミング読み取り

import json

# 大きなファイルの場合

with open('large.json', 'r', encoding='utf-8') as f:

# 一度にすべて読み込む代わりに

for line in f:

try:

data = json.loads(line)

# 各行を処理

process_data(data)

except json.JSONDecodeError:

continue

ijsonを使用(ストリーミング)

import ijson

# 大きなJSONファイルをストリーミング

with open('large.json', 'rb') as f:

objects = ijson.items(f, 'item')

for obj in objects:

# 各アイテムを処理

print(obj)

実用例

API リクエスト

import json

import requests

# APIからデータを取得

response = requests.get('https://api.example.com/users')

users = response.json()

# または

users = json.loads(response.text)

for user in users:

print(f"{user['name']}: {user['email']}")

設定ファイル

import json

# config.json

config = {

"database": {

"host": "localhost",

"port": 5432,

"name": "mydb"

},

"api_key": "secret123",

"debug": True

}

# 設定を保存

with open('config.json', 'w') as f:

json.dump(config, f, indent=2)

# 設定を読み込み

with open('config.json', 'r') as f:

config = json.load(f)

db_host = config['database']['host']

データ変換

import json

import csv

# CSVをJSONに変換

def csv_to_json(csv_file, json_file):

data = []

with open(csv_file, 'r', encoding='utf-8') as f:

reader = csv.DictReader(f)

for row in reader:

data.append(row)

with open(json_file, 'w', encoding='utf-8') as f:

json.dump(data, f, indent=2, ensure_ascii=False)

csv_to_json('users.csv', 'users.json')

ネストされたデータへのアクセス

import json

data = {

"users": [

{

"name": "田中太郎",

"address": {

"city": "東京",

"zip": "100-0001"

}

}

]

}

# 安全なアクセス

def get_nested(data, *keys, default=None):

"""ネストされた辞書から値を安全に取得"""

for key in keys:

try:

data = data[key]

except (KeyError, TypeError, IndexError):

return default

return data

# 使用

city = get_nested(data, 'users', 0, 'address', 'city')

print(city) # 東京

missing = get_nested(data, 'users', 0, 'phone', default='N/A')

print(missing) # N/A

JSON Schema検証

import json

from jsonschema import validate, ValidationError

# スキーマ定義

schema = {

"type": "object",

"properties": {

"name": {"type": "string"},

"age": {"type": "number", "minimum": 0},

"email": {"type": "string", "format": "email"}

},

"required": ["name", "email"]

}

# データ検証

data = {

"name": "田中太郎",

"age": 30,

"email": "tanaka@example.com"

}

try:

validate(instance=data, schema=schema)

print("データは有効です")

except ValidationError as e:

print(f"検証エラー: {e.message}")

ベストプラクティス

1. 常にencoding指定

# 良い

with open('data.json', 'r', encoding='utf-8') as f:

data = json.load(f)

# 悪い(システム依存)

with open('data.json', 'r') as f:

data = json.load(f)

2. ensure_ascii=Falseを使用(日本語の場合)

# 読みやすい

json.dumps(data, ensure_ascii=False)

# 読みにくい

json.dumps(data) # \u エスケープ

3. エラーハンドリング

try:

with open('data.json', 'r', encoding='utf-8') as f:

data = json.load(f)

except FileNotFoundError:

print("ファイルが見つかりません")

except json.JSONDecodeError:

print("無効なJSON")

except Exception as e:

print(f"エラー: {e}")

4. コンテキストマネージャを使用

# 良い

with open('data.json', 'w', encoding='utf-8') as f:

json.dump(data, f)

# 悪い(ファイルが閉じられない可能性)

f = open('data.json', 'w')

json.dump(data, f)

f.close()

よくある落とし穴

1. タプルはリストになる

data = {"coords": (10, 20)}

json_str = json.dumps(data)

parsed = json.loads(json_str)

print(type(parsed['coords'])) # <class 'list'>, not tuple

2. 辞書のキーは文字列のみ

data = {1: "one", 2: "two"}

json_str = json.dumps(data)

parsed = json.loads(json_str)

print(parsed) # {"1": "one", "2": "two"}

3. 循環参照

data = {"name": "田中"}

data["self"] = data # 循環参照

# エラー

json.dumps(data) # ValueError: Circular reference detected

まとめ

クイックリファレンス

import json

# 読み取り

data = json.loads(json_string) # 文字列から

data = json.load(file) # ファイルから

# 書き込み

json_string = json.dumps(data) # 文字列へ

json.dump(data, file) # ファイルへ

# オプション

json.dumps(data,

indent=2, # フォーマット

ensure_ascii=False, # 日本語そのまま

sort_keys=True # キーをソート

)

よく使うパターン

# 美しいJSON出力

with open('data.json', 'w', encoding='utf-8') as f:

json.dump(data, f, indent=2, ensure_ascii=False)

# 安全な読み取り

try:

with open('data.json', 'r', encoding='utf-8') as f:

data = json.load(f)

except (FileNotFoundError, json.JSONDecodeError) as e:

print(f"エラー: {e}")

data = {}

PythonのJSONサポートで、データ処理を簡単に!

Share:

関連記事

Read in English