csv-parse の使い方 — Node.js向けCSVパーサーの決定版
一言でいうと
csv-parse は、CSV テキストを配列やオブジェクトに変換する Node.js 向けパーサーです。Node.js の stream.Transform API を実装しており、小さなファイルから大規模データセットまで柔軟に対応できます。
どんな時に使う?
- CSVファイルのインポート処理 — ユーザーがアップロードしたCSVファイルをパースしてデータベースに投入する
- 大容量CSVのストリーム処理 — 数GB級のCSVファイルをメモリを圧迫せずに1行ずつ処理する
- 外部システムとのデータ連携 — 他システムから受け取ったCSV/TSVデータをアプリケーション内のオブジェクトに変換する
インストール
# npm
npm install csv-parse
# yarn
yarn add csv-parse
# pnpm
pnpm add csv-parse
CSV生成(stringify)や変換(transform)も必要な場合は、
npm install csvで関連パッケージを一括インストールできます。
基本的な使い方
csv-parse には主に4つのAPIフレーバーがあります。最もシンプルな Sync API と、実務で頻出する Callback API を紹介します。
Sync API(同期処理)
import { parse } from "csv-parse/sync";
const input = `name,age,city
Alice,30,Tokyo
Bob,25,Osaka`;
const records: Record<string, string>[] = parse(input, {
columns: true, // ヘッダー行をキーとしてオブジェクトに変換
skip_empty_lines: true,
});
console.log(records);
// [
// { name: 'Alice', age: '30', city: 'Tokyo' },
// { name: 'Bob', age: '25', city: 'Osaka' }
// ]
注意: Sync API はデータ全体をメモリに載せるため、大容量ファイルには向きません。
Callback API(コールバック)
import { parse } from "csv-parse";
const input = `name,age,city
Alice,30,Tokyo
Bob,25,Osaka`;
parse(input, { columns: true }, (err, records: Record<string, string>[]) => {
if (err) {
console.error(err);
return;
}
console.log(records);
});
Stream API(大容量ファイル向け)
import fs from "node:fs";
import { parse } from "csv-parse";
const parser = fs
.createReadStream("/path/to/large-file.csv")
.pipe(parse({ columns: true }));
for await (const record of parser) {
// 1行ずつ処理(メモリ効率が良い)
console.log(record);
}
よく使うAPI・オプション
1. columns — ヘッダー行をキーにしてオブジェクト化
import { parse } from "csv-parse/sync";
const input = `id,name,email
1,Alice,alice@example.com
2,Bob,bob@example.com`;
// columns: true でヘッダー行を自動的にキーとして使用
const records = parse(input, { columns: true });
// => [{ id: '1', name: 'Alice', email: 'alice@example.com' }, ...]
// カスタムカラム名を指定することも可能
const records2 = parse(input, {
columns: ["user_id", "user_name", "user_email"],
from_line: 2, // 元のヘッダー行をスキップ
});
// => [{ user_id: '1', user_name: 'Alice', user_email: 'alice@example.com' }, ...]
2. delimiter — 区切り文字の変更(TSV対応など)
import { parse } from "csv-parse/sync";
// タブ区切り(TSV)
const tsv = `name\tage\tcity
Alice\t30\tTokyo`;
const records = parse(tsv, {
columns: true,
delimiter: "\t",
});
// => [{ name: 'Alice', age: '30', city: 'Tokyo' }]
3. cast — 型変換
import { parse } from "csv-parse/sync";
const input = `name,age,active
Alice,30,true
Bob,25,false`;
const records = parse(input, {
columns: true,
cast: (value, context) => {
// 数値カラムを number に変換
if (context.column === "age") {
return parseInt(value, 10);
}
// boolean カラムを boolean に変換
if (context.column === "active") {
return value === "true";
}
return value;
},
});
console.log(records);
// [
// { name: 'Alice', age: 30, active: true },
// { name: 'Bob', age: 25, active: false }
// ]
4. skip_empty_lines / skip_records_with_error — 不正行のスキップ
import { parse } from "csv-parse/sync";
const input = `name,age
Alice,30
Bob,25
Charlie,invalid`;
const records = parse(input, {
columns: true,
skip_empty_lines: true, // 空行をスキップ
skip_records_with_error: true, // パースエラーの行をスキップ
});
5. on_record — レコード単位のフィルタリング・変換
import { parse } from "csv-parse/sync";
const input = `name,age,city
Alice,30,Tokyo
Bob,17,Osaka
Charlie,45,Nagoya`;
const records = parse(input, {
columns: true,
cast: (value, context) => {
if (context.column === "age") return parseInt(value, 10);
return value;
},
on_record: (record) => {
// 18歳未満を除外(undefinedを返すとスキップ)
if (record.age < 18) return undefined;
// フィールドを追加して返す
return { ...record, processed: true };
},
});
console.log(records);
// [
// { name: 'Alice', age: 30, city: 'Tokyo', processed: true },
// { name: 'Charlie', age: 45, city: 'Nagoya', processed: true }
// ]
類似パッケージとの比較
| 特徴 | csv-parse | papaparse | fast-csv |
|---|---|---|---|
| ストリーム対応 | ✅ Node.js Transform Stream | ✅(Node.js版) | ✅ |
| ブラウザ対応 | ✅ | ✅(メイン用途) | ❌ |
| Sync API | ✅ | ✅ | ❌ |
| TypeScript型定義 | ✅ 同梱 | ✅ @types/papaparse | ✅ 同梱 |
| 外部依存 | 0 | 0 | 1(@fast-csv/parse) |
| 大規模データ | ◎ 設計思想として重視 | ○ | ◎ |
| 学習コスト | 低〜中 | 低 | 低〜中 |
選定の目安:
- Node.js バックエンド中心 →
csv-parse(安定性・実績・エコシステム) - ブラウザ中心 →
papaparse(ブラウザファーストの設計) - パース&生成を一体で →
fast-csv(parse/format が統合)
注意点・Tips
1. Sync API と Stream API のインポートパスが異なる
// ❌ 間違い:sync を使いたいのに通常のパスからインポート
import { parse } from "csv-parse";
// ✅ 正しい:sync 版は専用サブパスからインポート
import { parse } from "csv-parse/sync";
2. デフォルトではすべての値が string になる
columns: true を指定しても、値はすべて文字列です。数値や真偽値が必要な場合は cast オプションを明示的に設定してください。
3. BOM(Byte Order Mark)付きUTF-8の対処
Excel で保存した CSV は BOM 付きになることがあります。bom: true を指定すると自動除去されます。
const records = parse(input, {
columns: true,
bom: true, // BOM を自動除去
});
4. 大容量ファイルは必ず Stream API を使う
Sync API や Callback API はデータ全体をメモリに保持します。数十MB以上のファイルを扱う場合は、Stream API(for await...of または pipe)を使いましょう。
5. info プロパティでパース状況を確認できる
import { parse } from "csv-parse";
const parser = parse({ columns: true });
parser.on("end", () => {
console.log(parser.info);
// { bytes: 1024, columns: true, comment_lines: 0,
// empty_lines: 0, invalid_field_length: 0,
// lines: 100, records: 99 }
});
デバッグやログ出力に便利です。
まとめ
csv-parse は、2010年から開発が続く Node.js 向け CSV パーサーの定番ライブラリです。Sync / Callback / Stream と3つの API スタイルを備え、小規模なスクリプトから大規模データパイプラインまで同じライブラリで対応できます。外部依存ゼロ・TypeScript 型定義同梱という点も、プロダクション環境での採用を後押しする安心材料です。