Python で JSONL を扱う:読み取り・書き込み・解析
Python で JSONL(JSON Lines)ファイルを扱うための完全ガイド。組み込みモジュール、pandas、高性能ライブラリを使用して JSONL データの読み取り、書き込み、解析、ストリーミングを学びます。
最終更新:2026年2月
なぜ Python で JSONL を扱うのか?
Python は JSONL ファイルを扱うための最も人気のある言語です。組み込みの json モジュールが JSON 解析をすぐにサポートし、ファイルのイテレーションはデフォルトでメモリ効率が良く、pandas や orjson などの強力なライブラリが専門的なワークフロー向けに提供されています。機械学習データセット、アプリケーションログ、API レスポンスのいずれを処理する場合でも、Python は JSONL の処理を簡単にします。
JSONL(JSON Lines)は1行に1つの JSON オブジェクトを格納するため、ストリーミング、追記専用ロギング、すべてをメモリに読み込まずに大規模データセットを処理するのに最適です。Python の行ごとのファイル読み取りはこの形式と完璧に適合します。このガイドでは、JSONL を読み取る3つのアプローチ、書き込む2つのアプローチ、そしてメモリに収まりきらないファイルの処理方法を学びます。
Python で JSONL ファイルを読み取る
Python で JSONL ファイルを読み取る方法はいくつかあり、それぞれ異なる用途に適しています。標準の json モジュールはほとんどのシナリオで機能し、pandas は表形式の分析に便利で、ジェネレーターは大容量ファイルに最適です。
最も簡単なアプローチは Python 組み込みの json モジュールを使用します。ファイルを開き、行ごとにイテレートし、各行を json.loads() で解析します。すべてのレコードがメモリ上のリストに読み込まれます。
import jsonrecords = []with open('data.jsonl', 'r', encoding='utf-8') as f:for line in f:line = line.strip()if line: # Skip empty linesrecords.append(json.loads(line))print(f'Loaded {len(records)} records')print(records[0])
JSONL データが表形式(すべてのレコードに同じキーがある)の場合、pandas は1つの関数呼び出しで直接 DataFrame に読み込むことができます。構造化された JSONL データの分析を始める最速の方法です。
import pandas as pd# Read entire file into a DataFramedf = pd.read_json('data.jsonl', lines=True)print(df.head())print(f'Shape: {df.shape}')# For large files, read in chunkschunks = pd.read_json('large.jsonl', lines=True, chunksize=10000)for chunk in chunks:# Process each chunk (DataFrame)print(f'Chunk shape: {chunk.shape}')
メモリに収まらないほど大きなファイルには、ジェネレーター関数を使用します。一度に1レコードずつ返すため、ファイルサイズに関係なくメモリ使用量が一定に保たれます。本番のデータパイプラインで推奨されるパターンです。
import jsonfrom typing import Iterator, Anydef read_jsonl(path: str) -> Iterator[dict[str, Any]]:"""Read a JSONL file lazily, yielding one record at a time."""with open(path, 'r', encoding='utf-8') as f:for line_num, line in enumerate(f, 1):line = line.strip()if not line:continuetry:yield json.loads(line)except json.JSONDecodeError as e:print(f'Skipping invalid JSON at line {line_num}: {e}')# Process records one at a timefor record in read_jsonl('large_data.jsonl'):process(record) # Only one record in memory at a time
Python で JSONL ファイルを書き込む
JSONL ファイルの書き込みは簡単です。各レコードを JSON 文字列にシリアライズし、改行文字を追加します。重要なルールは1行に1つの JSON オブジェクト、末尾のカンマやラッピング配列は不要です。
json.dumps() を使用して各レコードをシリアライズし、改行に続けて書き込みます。ensure_ascii=False を設定すると、出力内の中国語、日本語、絵文字などの Unicode 文字が保持されます。
import jsonrecords = [{"id": 1, "name": "Alice", "age": 30},{"id": 2, "name": "Bob", "age": 25},{"id": 3, "name": "Charlie", "age": 35},]with open('output.jsonl', 'w', encoding='utf-8') as f:for record in records:f.write(json.dumps(record, ensure_ascii=False) + '\n')print(f'Wrote {len(records)} records to output.jsonl')
データがすでに pandas DataFrame にある場合、to_json() を orient='records' と lines=True で使用して、JSONL として直接エクスポートできます。これは pd.read_json() の lines=True の逆操作です。
import pandas as pddf = pd.DataFrame([{"id": 1, "name": "Alice", "age": 30},{"id": 2, "name": "Bob", "age": 25},{"id": 3, "name": "Charlie", "age": 35},])# Write DataFrame to JSONLdf.to_json('output.jsonl', orient='records', lines=True, force_ascii=False)print(f'Wrote {len(df)} records to output.jsonl')
JSONL 向け Python ライブラリ
Python には、異なるパフォーマンス特性を持つ複数の JSON 解析ライブラリがあります。適切なものを選ぶには、ファイルサイズとパフォーマンス要件に応じて判断します。
json(標準ライブラリ)
組み込みPython 組み込みの json モジュールはインストール不要でどこでも動作します。ほとんどの JSONL ワークロードに十分で、すべての標準 JSON 型をサポートします。数百 MB までのファイルであれば十分なパフォーマンスです。
orjson
最速orjson は Rust で書かれた最速の Python JSON ライブラリです。標準の json モジュールと比較して2〜10倍高速な解析とシリアライズを提供します。文字列ではなくバイトを出力し、dataclass、datetime、numpy、UUID 型をネイティブにサポートします。
ujson
高速ujson(UltraJSON)は C ベースの JSON ライブラリで、標準の json モジュールより2〜5倍高速です。API は組み込みの json モジュールとほぼ同一のため、ドロップイン置換として使用できます。互換性と速度のバランスが良い選択肢です。
大容量 JSONL ファイルのストリーミング
ギガバイト規模の JSONL ファイルを処理する場合、データをバッチで読み取り、変換、書き込みするストリーミングアプローチが必要です。メモリ使用量を一定に保ち、進捗追跡も可能です。
import jsonimport sysdef process_large_jsonl(input_path: str,output_path: str,batch_size: int = 1000) -> int:"""Stream-process a large JSONL file in batches."""processed = 0batch: list[dict] = []with open(input_path, 'r') as fin, \open(output_path, 'w') as fout:for line in fin:line = line.strip()if not line:continuerecord = json.loads(line)# Transform the recordrecord['processed'] = Truebatch.append(record)if len(batch) >= batch_size:for r in batch:fout.write(json.dumps(r) + '\n')processed += len(batch)batch.clear()print(f'\rProcessed {processed} records...', end='')# Write remaining recordsfor r in batch:fout.write(json.dumps(r) + '\n')processed += len(batch)print(f'\nDone. Processed {processed} records total.')return processed# Usageprocess_large_jsonl('input.jsonl', 'output.jsonl', batch_size=5000)
このパターンは固定サイズのバッチでレコードを処理することで、メモリ使用量を一定に保ちます。batch_size パラメータでメモリ使用量と I/O 効率のトレードオフを制御します。ほとんどのシステムでは、1,000〜10,000 レコードのバッチが適切です。進捗インジケーターは長時間実行ジョブの監視に役立ちます。
無料 JSONL ツールを試す
コードを書きたくないですか?無料のオンラインツールを使って、JSONL ファイルの表示、検証、変換をブラウザで直接行えます。