CSV 无处不在——Excel 导出、数据库备份、埋点平台报表、遗留系统接口,默认格式几乎都是 CSV。但你的 API 通常只认 JSON。CSV→JSON 是现代开发中最高频的数据处理任务之一,而且坑比想象中多。
为什么要把 CSV 转成 JSON?
| 场景 | 原因 |
|---|---|
| REST API 请求体 | 绝大多数 API 只接受/返回 JSON |
| NoSQL 数据库导入 | MongoDB、DynamoDB 使用 JSON 文档格式 |
| 前端 JavaScript 处理 | JSON.parse() 原生支持;CSV 需要额外解析器 |
| 数据管道 ETL | JSON 是现代数据流转的通用格式 |
| 从 Excel 管理配置 | 运营团队用表格维护配置,程序消费 JSON |
CSV 结构基础
CSV(逗号分隔值)文件由两部分组成:
- 表头行(可选但强烈建议保留):列名
- 数据行:每行一条记录,值之间用分隔符隔开
id,name,email,age,active
1,张三,[email protected],30,true
2,李四,[email protected],25,false
3,王五,[email protected],35,true
转换后的 JSON 数组:
[
{ "id": "1", "name": "张三", "email": "[email protected]", "age": "30", "active": "true" },
{ "id": "2", "name": "李四", "email": "[email protected]", "age": "25", "active": "false" },
{ "id": "3", "name": "王五", "email": "[email protected]", "age": "35", "active": "true" }
]
注意:默认情况下所有值都是字符串。类型推断(把 "30" 转成数字 30)是可选行为,取决于工具配置。
常见转换场景
基础平铺转换
最简单的情况:表头直接映射为 JSON 键名。
product_id,name,price,in_stock
P001,Widget,9.99,true
P002,Gadget,24.99,false
转换结果:
[
{ "product_id": "P001", "name": "Widget", "price": "9.99", "in_stock": "true" },
{ "product_id": "P002", "name": "Gadget", "price": "24.99", "in_stock": "false" }
]
带类型推断的转换
给 API 用时,通常需要数字是数字、布尔值是布尔值:
[
{ "product_id": "P001", "name": "Widget", "price": 9.99, "in_stock": true },
{ "product_id": "P002", "name": "Gadget", "price": 24.99, "in_stock": false }
]
大多数转换工具(包括 ZeroTool)都提供”解析类型”选项。
含逗号的字段
CSV 通过引号处理包含逗号的值:
city,description
上海,"中国最大城市,金融中心"
北京,"中国首都,政治文化中心"
正确的 JSON 输出:
[
{ "city": "上海", "description": "中国最大城市,金融中心" },
{ "city": "北京", "description": "中国首都,政治文化中心" }
]
用简单的字符串 split 按逗号切割会把这类字段打烂。务必用专业 CSV 解析器。
含换行符的字段
被引号包裹的字段可以跨行:
id,notes
1,"第一行
第二行"
2,"单行内容"
这是合法的 CSV,但解析器必须支持多行字段。
制表符分隔(TSV)
部分系统导出使用 Tab 而非逗号分隔:
name score grade
张三 95 A
李四 82 B
转换时指定分隔符为 \t,大多数工具都支持自定义分隔符。
边界情况处理
缺失值
id,name,email
1,张三,[email protected]
2,李四,
3,,[email protected]
缺失值可以转为空字符串 "" 或 null,取决于工具设置:
[
{ "id": "1", "name": "张三", "email": "[email protected]" },
{ "id": "2", "name": "李四", "email": "" },
{ "id": "3", "name": "", "email": "[email protected]" }
]
无表头行
CSV 没有表头时可以:
- 自动生成列名:
col1、col2、col3 - 手动指定列名后再转换
重复列名
value,value,value
1,2,3
不同工具处理方式不同:有的会加后缀(value、value_1、value_2),有的直接覆盖。建议在转换前先处理重复列名。
代码实现
JavaScript(Papa Parse)
Papa Parse 是 JavaScript 生态中最成熟的 CSV 库:
npm install papaparse
const Papa = require('papaparse');
const fs = require('fs');
const csv = fs.readFileSync('data.csv', 'utf8');
const result = Papa.parse(csv, {
header: true, // 第一行作为键名
dynamicTyping: true, // 自动转换数字和布尔值
skipEmptyLines: true,
});
console.log(JSON.stringify(result.data, null, 2));
Python(标准库 csv 模块)
import csv
import json
with open('data.csv', newline='', encoding='utf-8') as f:
reader = csv.DictReader(f)
rows = list(reader)
print(json.dumps(rows, indent=2, ensure_ascii=False))
需要类型推断时,手动转换每行的值:
def coerce(value):
if value.lower() in ('true', 'false'):
return value.lower() == 'true'
try:
return int(value)
except ValueError:
pass
try:
return float(value)
except ValueError:
pass
return value
rows = [{k: coerce(v) for k, v in row.items()} for row in rows]
命令行(csvkit)
# 安装
pip install csvkit
# CSV 转 JSON
csvjson data.csv
# 美化输出
csvjson data.csv | jq .
Miller(mlr)
Miller 是功能强大的数据流处理工具,支持多种格式互转:
# macOS 安装
brew install miller
# CSV 转 JSON
mlr --csv --ojson cat data.csv
JSON 转回 CSV
有时需要把 JSON 数组转成 CSV,方便在 Excel 或 Google Sheets 里分析:
[
{ "id": 1, "name": "张三", "score": 95 },
{ "id": 2, "name": "李四", "score": 82 }
]
期望的 CSV:
id,name,score
1,张三,95
2,李四,82
嵌套对象是难点——大多数转换工具会把嵌套键用分隔符展平:user.name、user.email。ZeroTool 的转换器自动处理这种情况。
大文件性能建议
处理百万行级别的 CSV 时:
- 流式处理:逐行处理而非一次性加载全部内容到内存
- NDJSON 输出:换行符分隔的 JSON(每行一个对象)比单个超大数组更适合流式传输
- 关闭类型推断:对已知 schema 的数据禁用类型推断可显著降低 CPU 开销
// Papa Parse 流式输出 NDJSON
Papa.parse(stream, {
header: true,
step: (row) => process.stdout.write(JSON.stringify(row.data) + '\n'),
complete: () => console.error('完成'),
});
在线转换工具
不想写代码?ZeroTool 的 CSV↔JSON 在线转换器完全在浏览器内运行,支持粘贴文本或上传文件,可调整分隔符、类型解析、表头处理等选项,转换结果可直接下载。不上传任何数据到服务器。