JSON 转 CSV 完整指南 - 转换技巧与最佳实践(2026)

1329 字
7 分钟
JSON 转 CSV 完整指南 - 转换技巧与最佳实践(2026)

📖 为什么需要 JSON 转 CSV 完整指南?#

在实际工作中,简单的 JSON 转 CSV 可能遇到各种复杂情况:

  • 嵌套的 JSON 结构如何处理?
  • 特殊字符(逗号、引号、换行)怎么转义?
  • 大型数据集如何优化性能?
  • 不同编码格式如何选择?

本指南将详细解答这些问题,让你成为 JSON 转 CSV 的专家。


🔍 JSON 与 CSV 格式对比#

数据结构差异#

JSON(JavaScript Object Notation):

  • ✅ 支持复杂嵌套结构
  • ✅ 支持多种数据类型
  • ✅ 自描述性(字段名包含在内)
  • ❌ 不适合表格数据展示

CSV(Comma-Separated Values):

  • ✅ 简单的表格格式
  • ✅ Excel 原生支持
  • ✅ 文件体积小
  • ❌ 只支持二维数据

转换挑战#

graph TD A[JSON 数据] --> B{数据结构} B -->|扁平数组 | C[直接转换] B -->|嵌套对象 | D[扁平化处理] B -->|数组嵌套 | E[展开或合并] B -->|混合类型 | F[类型统一] C --> G[CSV 输出] D --> G E --> G F --> G

📝 转换规则详解#

1. 扁平 JSON 转换#

最简单的情况:

输入:

[
{"name": "张三", "age": 25, "city": "北京"},
{"name": "李四", "age": 30, "city": "上海"}
]

输出:

name,age,city
张三,25,北京
李四,30,上海

2. 嵌套对象处理#

方案 A:点号表示法(推荐)

输入:

[
{
"name": "张三",
"address": {
"city": "北京",
"district": "朝阳"
}
}
]

输出:

name,address.city,address.district
张三,北京,朝阳

方案 B:JSON 字符串

name,address
张三,"{\"city\":\"北京\",\"district\":\"朝阳\"}"

3. 数组处理#

方案 A:展开为多行

输入:

{
"name": "张三",
"skills": ["JavaScript", "Python", "Java"]
}

输出:

name,skill
张三,JavaScript
张三,Python
张三,Java

方案 B:合并为字符串

name,skills
张三,"JavaScript,Python,Java"

4. 特殊字符转义#

CSV 转义规则:

字符转义方式示例
逗号用引号包裹"Hello, World"
双引号doubling"He said ""Hi"""
换行符用引号包裹"Line1\nLine2"
制表符用引号包裹"Col1\tCol2"

示例:

[
{
"quote": "He said \"Hello, World!\"",
"multiline": "Line 1\nLine 2"
}
]

转换为:

quote,multiline
"He said ""Hello, World!""","Line 1
Line 2"

🛠️ 高级转换技巧#

1. 字段筛选#

只导出需要的字段:

// 原始 JSON
[
{
"id": 1,
"name": "产品 A",
"price": 100,
"cost": 50,
"profit": 50
}
]
// 只导出部分字段
// 输出:name,price,profit
// 产品 A,100,50

2. 字段重命名#

// 映射规则
{
"user_name": "Username",
"user_email": "Email"
}
// 转换
{"user_name": "张三", "user_email": "zhangsan@example.com"}
// 输出:Username,Email
// 张三,zhangsan@example.com

3. 数据格式化#

数值格式化:

// 保留 2 位小数
{
"price": 99.999
}
// 输出:99.99

日期格式化:

// ISO 日期 → 本地格式
{
"created_at": "2026-01-01T00:00:00Z"
}
// 输出:2026-01-01

货币格式化:

// 添加货币符号
{
"amount": 1000
}
// 输出:¥1,000.00

4. 空值处理#

// 策略选择
{
"name": "张三",
"age": null,
"email": ""
}
// 方案 1:保留空值
// 张三,,
// 方案 2:填充默认值
// 张三,0,N/A
// 方案 3:跳过该字段
// 张三

📊 性能优化#

1. 大数据量处理#

分块处理:

// 100000 条数据
const batchSize = 10000;
for (let i = 0; i < data.length; i += batchSize) {
const batch = data.slice(i, i + batchSize);
convertToCSV(batch);
}

流式处理:

// 边读边写,节省内存
readStream
.pipe(transform)
.pipe(writeStream);

2. 编码优化#

UTF-8 with BOM(推荐用于 Excel):

const csvWithBOM = '\uFEFF' + csvContent;

压缩输出:

// 对于超大文件
const compressed = pako.gzip(csvContent);

3. 性能对比#

数据量普通转换优化后提升
1,000 条50ms30ms40%
10,000 条500ms200ms60%
100,000 条5s1.5s70%
1,000,000 条50s12s76%

💼 实战案例#

案例 1:电商订单导出#

需求:将订单 API 的 JSON 响应转为 CSV,供财务对账。

原始数据:

{
"orders": [
{
"id": "ORD001",
"customer": {"name": "张三", "phone": "138****1234"},
"items": [
{"product": "iPhone", "price": 7999, "qty": 1}
],
"total": 7999,
"status": "completed"
}
]
}

处理步骤:

  1. 提取 orders 数组
  2. 扁平化 customer 对象
  3. 展开 items 数组
  4. 格式化金额

最终 CSV:

order_id,customer_name,customer_phone,product,price,quantity,total,status
ORD001,张三,138****1234,iPhone,7999,1,7999,completed

案例 2:用户数据迁移#

需求:从 MongoDB 导出用户数据,导入 MySQL。

MongoDB 数据:

[
{
"_id": "507f1f77bcf86cd799439011",
"username": "zhangsan",
"profile": {
"realname": "张三",
"avatar": "https://..."
},
"created_at": "2026-01-01T00:00:00Z"
}
]

目标 CSV:

id,username,realname,avatar,created_at
507f1f77bcf86cd799439011,zhangsan,张三,https://...,2026-01-01

案例 3:日志数据分析#

需求:将 JSON 格式的日志转为 CSV,在 Excel 中分析。

日志数据:

[
{
"timestamp": 1704067200000,
"level": "INFO",
"message": "User login",
"context": {
"userId": 123,
"ip": "192.168.1.1"
}
}
]

CSV 输出:

timestamp,level,message,userId,ip
2026-01-01 00:00:00,INFO,User login,123,192.168.1.1

🎯 最佳实践#

1. 数据验证#

转换前检查:

function validateJSON(data) {
// 检查是否为数组
if (!Array.isArray(data)) {
throw new Error('JSON 必须是数组格式');
}
// 检查字段一致性
const keys = Object.keys(data[0]);
for (let item of data) {
if (Object.keys(item).sort().join(',') !== keys.sort().join(',')) {
console.warn('字段不一致');
}
}
}

2. 错误处理#

try {
const csv = convert(json);
} catch (error) {
if (error instanceof SyntaxError) {
console.error('JSON 格式错误');
} else if (error.message.includes('escape')) {
console.error('特殊字符转义失败');
}
}

3. 测试用例#

// 边界测试
const testCases = [
{ input: [], expected: '' },
{ input: [{}], expected: '\n' },
{ input: [{a: 1}], expected: 'a\n1' },
{ input: [{a: ','}], expected: 'a\n","' },
];

❓ 常见问题#

Q1: 如何保留前导零?#

答:在字段前添加制表符或使用文本格式:

id
\t00123

Q2: CSV 文件在 Excel 中乱码?#

答:

  1. 使用 UTF-8 with BOM 编码
  2. 或在 Excel 中使用”数据→从文本导入”
  3. 选择正确的编码(UTF-8)

Q3: 数字精度丢失?#

答:

  • 大数字用引号包裹:"123456789012345"
  • 或添加制表符:\t123456789012345

Q4: 如何处理动态字段?#

答:

// 收集所有字段
const allKeys = new Set();
data.forEach(item => {
Object.keys(item).forEach(key => allKeys.add(key));
});
// 使用 allKeys 作为表头

🚀 工具推荐#

在线工具:

编程库:

  • JavaScript: json2csv
  • Python: pandas
  • Node.js: csv-stringify

相关资源#

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

最后更新于 2026-03-29,距今已过 200 天

部分内容可能已过时

公告
🎉 已升级 2.0 版本,欢迎使用。
分类
标签
站点统计
文章
197
分类
24
标签
747
总字数
334,099
运行时长
0 天
最后活动
0 天前

目录