Convert JSON to CSV: Complete Guide With Examples
Learn how to convert JSON to CSV for spreadsheets, databases, and data analysis. Covers flattening nested objects, handling edge cases, and programmatic conversion in JavaScript and Python.
当您需要 JSON 转 CSV 转换时
JSON 是 API 和 Web 应用程序的默认格式,但一旦数据需要离开开发者生态系统——进入电子表格、商业智能工具、数据库导入或发送给利益相关者的报告——CSV 通常是预期的格式。
JSON 转 CSV 转换常见场景:
- 导出 API 数据 — 从 REST API 中提取记录并将其加载到 Excel 或 Google Sheets 中进行分析。
- 数据库导入 — 许多数据库(PostgreSQL、MySQL、SQLite)支持开箱即用的 CSV 导入,但不支持 JSON。
- 报告 — 非技术利益相关者需要以他们可以在电子表格中打开的格式提供数据,而不是 JSON 查看器。
- 数据管道 — 传统的 ETL 系统通常期望 CSV 作为阶段之间的交换格式。
自己试试: 将 JSON 数组粘贴到我们的 JSON 转 CSV 转换器中,立即下载准备好的 CSV 文件。
简单转换演示
简单的情况:您有一个扁平对象的 JSON 数组,其中每个对象都有相同的键。这直接映射到 CSV 表。
输入 JSON:
[
{ "name": "Alice", "age": 30, "city": "Portland" },
{ "name": "Bob", "age": 25, "city": "Seattle" },
{ "name": "Carol", "age": 35, "city": "Denver" }
]
输出 CSV:
name,age,city
Alice,30,Portland
Bob,25,Seattle
Carol,35,Denver
对象的键成为列标题,每个对象成为一行。这是理想情况——对于大多数返回记录数组的 API 响应,它都能完美工作。
复杂性出现在您的 JSON 不是扁平时。嵌套对象、对象中的数组、缺失的键和混合类型都需要决定如何在扁平表中表示层次数据。
处理嵌套 JSON
现实世界中的 JSON 很少是扁平的。用户的 API 响应可能包括嵌套的地址对象、角色数组和不出现在每个记录上的可选字段。CSV 没有嵌套的概念,因此您需要一个扁平化策略。
策略 1:点符号表示法
最常见的方法。嵌套键用点连接形成单个列名。
输入:
[
{
"name": "Alice",
"address": {
"city": "Portland",
"state": "OR"
}
}
]
输出:
name,address.city,address.state
Alice,Portland,OR
点符号表示法在列名中保留了结构关系。它适用于一到两层嵌套,但对于深度嵌套数据(user.profile.settings.notifications.email)则显得笨重。
策略 2:每个叶子值的单独列
类似于点符号表示法,但使用自定义列名,省略嵌套层次。例如,address.city 变为仅 city。这产生更干净的标题,但需要手动列映射,并且如果不同的嵌套对象具有相同名称的键,则存在名称冲突的风险。
策略 3:将嵌套对象字符串化
对于无法很好映射到扁平列的复杂嵌套结构,将嵌套值序列化为 CSV 单元格中的 JSON 字符串。
输出:
name,address
Alice,"{""city"":""Portland"",""state"":""OR""}"
Bob,"{""city"":""Seattle"",""state"":""WA""}"
这保留了所有数据,但 CSV 单元格包含原始 JSON——对于电子表格用户来说并不理想。当 CSV 是将被代码再次解析的中间格式时,它是有效的。
比较扁平化方法
| 方法 | 可读性 | 数据丢失 | 深层嵌套 | 最佳适用场景 |
|---|---|---|---|---|
| 点符号表示法 | 良好 | 无 | 变得冗长 | 1-2 层嵌套 |
| 自定义列名 | 最佳 | 可能发生冲突 | 手动工作 | 已知、稳定的模式 |
| 字符串化 | 对人类不友好 | 无 | 处理任何深度 | 机器对机器的管道 |
处理对象中的数组
数组提出了不同的挑战。考虑一个具有多个角色的用户:
{
"name": "Alice",
"roles": ["admin", "editor", "viewer"]
}
您有几种选项在 CSV 中表示它:
- 作为分隔字符串连接: 在一个单元格中
admin;editor;viewer。简单但需要后续解析。 - 单独列:
roles.0,roles.1,roles.2。当最大数组长度已知且较小时有效。 - 单独行: 每个角色一行,用户的其他数据重复。这使数据非规范化,但避免了多值单元格。
- 字符串化: 在单元格中将
["admin","editor","viewer"]作为原始 JSON。保留结构以便后续处理。
正确的选择取决于谁使用 CSV。对于电子表格用户,分隔字符串的方法通常是最实用的。对于数据管道,字符串化保留了最多的信息。
边缘情况
每个 JSON 转 CSV 转换最终都会遇到这些情况。提前了解它们可以节省调试时间。
空值
JSON null 可以映射到一个空单元格、字面字符串 null 或自定义占位符。大多数工具使用空单元格,这对于电子表格是正确的,但失去了“null”(明确没有值)和“缺失键”(字段不存在)之间的区别。如果这个区别很重要,请使用 null 作为字面字符串。
混合类型
JSON 字段在一条记录中可能是字符串,而在另一条记录中可能是数字。CSV 列没有类型——一切都是字符串——因此这通常在 CSV 级别工作良好。问题出现在导入到类型系统(数据库、类型化数据框)时。转换后验证类型。
缺失键
当 JSON 数组中的对象并不都具有相同的键时,转换器需要构建所有对象的所有键的并集。这会生成一个包含所有可能列的标题行,而缺少键的对象在该列中会得到一个空单元格。
[
{ "name": "Alice", "age": 30 },
{ "name": "Bob", "city": "Seattle" }
]
输出:
name,age,city
Alice,30,
Bob,,Seattle
值中的特殊字符
包含逗号、双引号或换行符的 CSV 值必须用双引号括起来。如果值本身包含双引号,则通过将其加倍来转义。大多数转换库会自动处理此问题,但如果您正在构建自己的转换器,这是最常见的错误来源。
name,bio
Alice,"喜欢 ""JSON"" 和编码"
Bob,"波特兰,俄勒冈州"
编程转换
JavaScript / Node.js
对于简单的扁平数据,您可以在几行代码中将 JSON 转换为 CSV,而无需任何依赖:
const jsonToCsv = (data: Record<string, unknown>[]) => {
if (data.length === 0) return "";
const headers = Object.keys(data[0]);
const rows = data.map((row) =>
headers
.map((header) => {
const value = row[header] ?? "";
const str = String(value);
return str.includes(",") || str.includes('"') || str.includes("\\n")
? `"\${str.replace(/"/g, '""')}"`
: str;
})
.join(",")
);
return [headers.join(","), ...rows].join("\\n");
};
对于具有嵌套数据的生产使用,像 json2csv(来自 @json2csv/plainjs 包)这样的库处理扁平化、自定义转换和边缘情况:
import { Parser } from "@json2csv/plainjs";
import { flatten } from "@json2csv/transforms";
const parser = new Parser({
transforms: [flatten({ separator: "." })],
});
const csv = parser.parse(data);
Python
Python 的标准库提供了基本转换所需的一切:
import csv
import json
import io
def json_to_csv(data: list[dict]) -> str:
if not data:
return ""
output = io.StringIO()
writer = csv.DictWriter(output, fieldnames=data[0].keys())
writer.writeheader()
writer.writerows(data)
return output.getvalue()
对于嵌套 JSON,pandas 库可以在一次调用中扁平化并转换:
import pandas as pd
df = pd.json_normalize(data, sep=".")
df.to_csv("output.csv", index=False)
json_normalize 使用点符号表示法自动处理嵌套对象。它是将嵌套 API 响应转换为干净 CSV 文件的最快方法。
大文件考虑
当您的 JSON 文件达到数百兆字节或更多时,转换方法需要改变。将整个文件加载到内存中、解析它并在内存中构建 CSV 字符串可能会轻易超过您可用的 RAM。
流式解析器 是解决方案。它们不是加载整个文件,而是逐步处理它:
- Node.js: 使用
JSONStream或stream-json逐个对象解析 JSON 数组,将每个对象转换为 CSV 行,并将其写入输出流。无论文件大小如何,内存保持不变。 - Python:
ijson库提供了迭代 JSON 解析。将其与csv.writer结合写入文件句柄以实现恒定内存转换。 - CLI:
jq原生以流式方式处理 JSON。对于 JSON 转 CSV,像miller(mlr) 和csvkit这样的工具专为大规模格式转换而设计。
一个实用的经验法则:如果您的 JSON 文件小于 50 MB,内存转换是可以的。超过这个大小,请切换到流式方法。超过 1 GB,使用像 miller 这样的 CLI 工具或专用数据处理框架。
选择正确的方法
| 场景 | 推荐的方法 |
|---|---|
| 快速一次性转换 | 在线工具或浏览器转换器 |
| 扁平 JSON,小文件 | 内置语言库(csv 模块,简单的 JS 函数) |
| 嵌套 JSON,复杂模式 | pandas.json_normalize 或 @json2csv 结合扁平化转换 |
| 大文件(>50 MB) | 流式解析器(ijson、stream-json)或 CLI(miller) |
| 定期管道 | 使用库的脚本,集成到 CI/ETL 中 |
对于大多数开发者来说,快速转换路径就是他们所需的全部。粘贴 JSON,获取 CSV,继续前进。只有在数据嵌套、文件较大或转换在管道中无人值守运行时,复杂性才显得重要。
自己试试: 将您的 JSON 数据粘贴到我们的 JSON 转 CSV 转换器中,几秒钟内即可获得干净的 CSV 文件。需要反向转换?使用我们的 CSV 转 JSON 工具。