6.

NDJSON / JSONL (.ndjson / .jsonl) とは|1 行 1 JSON のストリーミング形式

編集
この記事の要点
  • NDJSON(Newline Delimited JSON)/ JSONL(JSON Lines)は 1 行 1 JSON オブジェクト として並べたテキスト形式。事実上同じ仕様
  • 拡張子は .ndjson / .jsonl。配列でくくらないため 追記が容易、ストリーミング処理に向く
  • 通常の JSON は全体を読まないと値が取り出せないが、NDJSON は 1 行ずつパース できるためメモリ効率が良い
  • jq -c で生成、jq でフィルタ、wc -l でレコード数カウントなど Unix パイプとの相性が抜群
  • ログ転送(Logstash・Fluentd)、ML データセット(OpenAI Fine-tuning / Hugging Face)、BigQuery / Snowflake のバルクロードで標準的に採用
  • 改行コードは \n 推奨。\r\n も許容されるが、文字列内に生の改行は含めない(JSON 仕様どおり \\n でエスケープ)
  • 末尾改行の有無は実装ごとに揺れるので、生成側は付ける / 消費側はどちらでも受ける、が安全

概要

NDJSON(Newline Delimited JSON)と JSONL(JSON Lines)は、1 行に 1 つの JSON オブジェクトを書き、改行で区切る テキストフォーマットです。両者は仕様としてはほぼ同一で、コミュニティの呼び名が分かれているだけです。拡張子は .ndjson.jsonl が両方使われ、ツール側はどちらも受け付けるのが普通です。

通常の JSON ファイルは [ {...}, {...}, {...} ] という配列でくくるため、全件読み込まないとパースを始められません。これに対し NDJSON はファイル全体が JSON ではなく、各行が独立した JSON なので、1 行読んでパース → 処理 → 次の行 というストリーミング処理が自然にできます。100 GB のデータでもメモリ数 MB で処理できる、というのが最大の利点です。

用途は ログ転送・ETL・機械学習データセット・データウェアハウスのバルクロード が中心です。OpenAI の Fine-tuning API、Hugging Face Datasets、Google BigQuery の NEWLINE_DELIMITED_JSON 形式、AWS Athena、Snowflake などが NDJSON を 標準入力フォーマット として採用しています。Logstash と Fluentd はログイベントを NDJSON でやり取りするのが基本動作です。

内部構造とサンプル

NDJSON の中身は単純です。各行が 1 つの有効な JSON オブジェクトであり、行と行の間に余計な区切り文字(カンマや配列のブラケット)は 入りません

{"id":1,"name":"alice","tags":["admin","ops"]}
{"id":2,"name":"bob","tags":["dev"]}
{"id":3,"name":"carol","tags":[]}

同じデータを通常の JSON で書くとこうなります。

[
  {"id":1,"name":"alice","tags":["admin","ops"]},
  {"id":2,"name":"bob","tags":["dev"]},
  {"id":3,"name":"carol","tags":[]}
]

違いは「外側の [ ] がない」「各要素の後ろのカンマがない」「1 行に 1 つ」の 3 点です。これにより NDJSON は 追記が tail -F で監視可能 になり、cat a.ndjson b.ndjson > merged.ndjson で単純連結できます。普通の JSON 配列だと連結に jq -s などの処理が必要になります。

主な用途

  • ログ配送: Fluentd・Logstash・Vector がイベントを NDJSON で書き出す。各行が 1 イベント、Elasticsearch / OpenSearch の Bulk API も NDJSON ベース
  • ETL の中間形式: S3 / GCS に NDJSON で吐いて、BigQuery / Snowflake / Redshift / Athena が読み込む。Parquet ほど効率は良くないが、人間が中身を読めるのが利点
  • ML データセット: OpenAI Fine-tuning は {"prompt":"...","completion":"..."} を 1 行ずつ並べた JSONL を受け付ける。Hugging Face Datasets も同様
  • クローラー出力: Scrapy などは scrapy crawl -o out.jsonl で結果を JSONL に書き出す。途中で落ちても部分結果が残るのが嬉しい
  • API のストリーミングレスポンス: ChatGPT の API がイベントを data: {...}\\n\\n 形式で返すのも、NDJSON の近縁(厳密には SSE)

関連形式との比較

項目NDJSON / JSONL通常の JSON 配列CSVParquet
1 行 1 レコード×—(バイナリ)
ストリーミング処理×
ネスト構造×
サイズ小(圧縮)
追記○(行追加するだけ)××(パーティション追加)
人間可読性×

NDJSON は「人間が読めて、追記でき、ストリームできる」中庸の選択肢です。長期保管やクエリ性能を最優先するなら Parquet、表計算ソフトで開きたいなら CSV、設定ファイルなら通常の JSON、と用途で選び分けます。

コマンド・ツール

# JSON 配列 → NDJSON
jq -c '.[]' input.json > output.ndjson

# NDJSON → JSON 配列
jq -s '.' input.ndjson > output.json

# 件数カウント
wc -l data.ndjson

# 特定フィールドだけ抽出
jq -r '.email' users.ndjson

# 条件フィルタ
jq -c 'select(.tags | index("admin"))' users.ndjson

# 並列処理(GNU parallel + jq)
cat huge.ndjson | parallel --pipe -j 8 'jq -c ".id"'

# BigQuery にロード
bq load --source_format=NEWLINE_DELIMITED_JSON \
   dataset.table gs://bucket/data.ndjson schema.json

# Elasticsearch Bulk API(NDJSON ベース)
curl -s -H 'Content-Type: application/x-ndjson' \
  -XPOST localhost:9200/_bulk --data-binary @bulk.ndjson

Python なら for line in open(path): obj = json.loads(line) の素朴なループで処理でき、pandas.read_json(path, lines=True) も対応。Node.js は readline モジュールで 1 行ずつ読み、Go は bufio.Scanner + json.Unmarshal が定番です。

注意点

  • 改行の取り扱い: 推奨は LF(\\n)。CRLF も多くの実装が許容するが、シェルパイプ経由で混ざると行数カウントがズレることがある
  • 整形 JSON は不可: 配列要素を改行で複数行に分けると 1 行 1 オブジェクトの前提が崩れる。生成側は必ず 1 行に圧縮 する(jq -c
  • 末尾改行: 仕様としてどちらも許容だが、付ける派が多数。wc -l でズレた場合はこれを疑う
  • 巨大行は重い: 1 行が数 MB を超えると jq--seq 系でも詰まりやすい。文字列フィールドに巨大データを入れず、別ファイル化する
  • 文字コード: UTF-8 が事実上必須。日本語などのマルチバイトは \\uXXXX エスケープと生の UTF-8 の両方が許容されるが、現代では生の UTF-8 のままが標準
  • セキュリティ: 信頼できないソースの NDJSON を eval や安直なテンプレートに流すと、" や制御文字でインジェクションが起きる。必ず JSON パーサ経由で取り扱う

関連リンク

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. SQL ダンプ(.sql)
  2. SQLite(.sqlite / .sqlite3 / .db)
  3. Parquet(.parquet)
  4. Avro(.avro)
  5. ORC(.orc)
  6. NDJSON / JSONL(.ndjson / .jsonl)
  7. BSON(.bson)
  8. Protocol Buffers(.proto)
  9. Feather / Arrow IPC(.feather / .ipc / .arrow)
  10. DB ダンプ(.dump / .bak)

最近更新/作成されたページ