みなさんは JSON や CSV に馴染みがあると思いますが、数 GB に及ぶ巨大な JSON ファイルを処理する際にメモリが圧迫されてクラッシュした経験や、CSV で複雑な入れ子構造のデータを記録する際にエスケープ処理に苦しんだ経験はありませんか?
現代の AI 学習や大量データ処理の分野で、静かにデファクトスタンダードとなりつつあるデータフォーマットが存在します。それが JSONL(JSON Lines) です。
JSONL の核心的価値:従来の JSON がストリーミング読み込みできず、CSV がネスト構造をサポートできないという 2 大課題を解決すること!
JSONL とは?1 分でわかる「1 行 1 JSON」の基本定義
JSONL の正式名称は JSON Lines です(NDJSON:Newline Delimited JSON と呼ばれることもあります)。そのコンセプトは非常にシンプルで、「各行が独立した 1 つの完全な JSON オブジェクトである」 という点です。
従来の JSON ファイルでは、最外層に巨大な角括弧 [] を配置して全体を囲み、各オブジェクト間をカンマ , で区切る必要があります。一方、JSONL は最外層の角括弧やカンマを完全に排除し、改行コード \n を使って各レコードを区切ります。

3 大主要データフォーマットの比較
理解を深めるために、JSONL、JSON、CSV を並べて比較してみましょう:
| データフォーマット | レイアウト構造 | 構造のネスト対応 | ストリーミング読み書き | 最適な利用シーン |
|---|---|---|---|---|
| JSON | 単一の階層構造ツリー、一括読み込みが必要 | ネイティブ対応 | 困難(ファイル全体読込が必要) | Web API 転送、設定ファイル |
| CSV | 2D 平面テーブル、カンマ区切り | 困難(エスケープや符号化が必要) | ネイティブ対応 | Excel レポート、平面データ |
| JSONL | 1 行 1 独立 JSON、改行区切り | ネイティブ対応 | 極めて優秀(逐行読込&追記) | AI 学習データセット、大量 Log 記録 |
なぜ AI モデル学習やビッグデータ ETL で JSONL が好まれるのか?
近年、OpenAI や Anthropic などの大規模言語モデル(LLM)の台頭に伴い、JSONL はファインチューニング(Fine-tuning)やデータセット準備の第一選択肢となっています。その背景には 2 つの大きな強みがあります:
1. メモリ消費量が非常に少ない(Streaming ストリーミング処理に対応)
学習データセットが 50 GB に達する場合、従来の JSON ファイルではプログラムが 50 GB 全体をメモリに読み込んで構文木を解析する必要があり、即座に Out-Of-Memory(OOM)エラーを引き起こします。
これに対して JSONL は 行単位のストリーミング読み込み(Line-by-line Streaming) に対応しています。プログラムは一度に 1 行(わずか数 KB)だけを読み込み、処理後にメモリを解放して次の行を読み込むことができます。
flowchart TD
subgraph TraditionalJSON["従来の JSON 読み込み方式"]
A1["50 GB の JSON ファイルを読み込み"] --> A2["ファイル全体の構文木を解析"]
A2 --> A3["メモリに一括で 50 GB ロード"]
A3 -->|ハイリスク| A4["メモリ溢れでクラッシュ (OOM)"]
end
subgraph JSONLStreaming["JSONL ストリーミング読み込み方式"]
B1["50 GB の JSONL ファイルを開く"] --> B2["第 1 行目 (5 KB) を読み込み"]
B2 --> B3["単一データを解析・処理"]
B3 --> B4["メモリ解放して次の行を読み込み"]
B4 --> B5["安定かつ効率的に大量データを処理"]
end
大量のデータ処理において、JSONL はメモリ消費量を O(N) から O(1) に削減します!
2. ロックフリーの追記(Append-Only Logging)に対応
分散システムやログ収集の現場で、ファイルの末尾にデータを追加したい場合:
- 従来の
JSON:ファイル全体を読み込み、末尾の]を削除し、カンマ,を追加して新しいデータを書き込み、再び]を付け直す必要があります。 - JSONL:ファイルの末尾に文字列と改行コード
\nを直接追記(append)するだけで書き込みが完了します。
3. ビッグデータの並列処理(Parallel Processing)
JSONL は各行が独立した JSON オブジェクトであるため、巨大なファイルを任意の改行位置で複数のブロックに分割し、複数の CPU コアや計算ノードに送信して互いに干渉することなく並列計算を行えます。
開発者が知っておくべき JSONL の 5 大厳格ルール
JSONL は柔軟性に優れていますが、パーサーが正常に読み込めるように公式仕様(jsonlines.org)で 5 つの厳格なフォーマット制限が定められています:
規約の詳細説明
| 規約番号 | 厳格ルール項目 | 説明と正しい例 |
|---|---|---|
| ルール 1 | 各行は有効な JSON であること | 独立して取り出した各行が標準の JSON.parse() で解析可能である必要があります。 |
| ルール 2 | エスケープなしの改行は禁止 | 文字列内に改行を含む場合、\n としてエスケープする必要があります。複数行レイアウトは禁止です。 |
| ルール 3 | 最外層の記号は禁止 | 最外層の角括弧 [] は禁止されており、行同士の間に カンマ , を付けてはいけません。 |
| ルール 4 | BOM なしの UTF-8 エンコーディング | 厳格に UTF-8 エンコーディングを使用し、BOM ヘッダーを含めてはなりません。 |
| ルール 5 | 原則として空行は含まない | すべての行が有効なデータである必要があり、ファイルの最終行のみ末尾の空改行が許容されます。 |
実踐解説:堅牢な JSONL 読み込みコードの書き方
実際の開発において、JSONL は スキーマレス(Schema-less) の特性を持つため、行ごとに Key が異なる場合があります。コードを記述する際は、以下の防御的原則に従うことを推奨します:
防御的コードの例(Python)
import json
def process_jsonl_file(file_path):
with open(file_path, "r", encoding="utf-8") as f:
for line_num, line in enumerate(f, 1):
# 1. 空行を自動的にスキップ(空行による解析失敗を防止)
line = line.strip()
if not line:
continue
try:
data = json.loads(line)
# 2. 防御的な値の取得:.get() を使用して KeyError を回避
user_id = data.get("id")
user_name = data.get("name", "Unknown")
# 3. フィールド型の識別(ポリモーフィックデータの処理)
doc_type = data.get("type", "default")
print(f"Line {line_num}: [{doc_type}] {user_id} - {user_name}")
except json.JSONDecodeError as e:
print(f"Error parsing line {line_num}: {e}")
# 読み込みを実行
process_jsonl_file("dataset.jsonl")
重要な防御テクニック:
strip()で前後の空白を除去し、キーの直接指定ではなく.get()を使用することで、実行時クラッシュの 90% 以上を防ぐことができます!
JSONL、JSON、CSV の利用シーン選択ガイド
JSONL の強力な機能を確認したところで、すべてのデータを JSONL に置き換えるべきでしょうか?答えは「ユースケースによる」です!
| 利用シーンのニーズ | 推奨フォーマット | 理由の説明 |
|---|---|---|
| Web フロントエンド/バックエンド API 転送 | JSON | ブラウザのネイティブサポートが高く、単一転送のデータ量が適度。 |
| 非エンジニア/マーケティング向けデータ出力 | CSV | Excel で直接開いて閲覧・編集可能。 |
| AI モデルのファインチューニング | JSONL | OpenAI / Anthropic API の公式指定学習フォーマット。 |
| システムの大量 Log 記録 | JSONL | 書き込みコストが低く、無制限の追記と低メモリ監視に対応。 |
| ビッグデータ ETL パイプライン | JSONL | 分散分割や並列処理が容易。 |
各フォーマットの特徴を理解し、適切なシーンで適切なツールを選択すれば、データ処理のパフォーマンスを大幅に向上させることができます!