← 全部文章

如何把 JSON 转成 CSV(以及反过来)

在 JavaScript、Python 和在线把 JSON 转成 CSV、CSV 转成 JSON。涵盖 array-of-objects 映射、引号规则、嵌套值与类型推断。

JSON 是 API 的语言,CSV 是表格、数据库和分析师的语言。两者之间的转换是日常工作 —— 把 API 响应导出到 Excel,或者把表格变成 JSON 用于导入。本指南讲解如何在 JavaScript、Python 中把 JSON 转为 CSV、再把 CSV 转回 JSON,以及如何在浏览器里即时完成;同时覆盖那些容易踩坑的边界情况(嵌套数据、引号、类型)。

核心映射:对象数组 ⇄ 行

CSV 文件是一张表:一行表头是列名,接下来一行一条记录。最自然地映射到这张表的 JSON 形态是一个 对象数组,每个对象是一行,每个键是一列。

// JSON
[
  { "id": 1, "name": "Ada Lovelace", "active": true },
  { "id": 2, "name": "Bob Khan", "active": false }
]
# CSV
id,name,active
1,Ada Lovelace,true
2,Bob Khan,false

表头是所有对象键的并集(这样字段不同的对象也能对齐),每一行从每一列拉取对应的值。

如何在 JavaScript 中把 JSON 转为 CSV

JavaScript 里没有内建的 JSON.toCSV,但转换本身很短。真正要做的只有 转义:任何含有逗号、双引号或换行的值都必须用双引号包起来,内部的引号要加倍。

function jsonToCsv(rows) {
  if (!rows.length) return '';
  const headers = [...new Set(rows.flatMap(Object.keys))];

  const escape = (v) => {
    if (v == null) return '';
    const s = typeof v === 'object' ? JSON.stringify(v) : String(v);
    return /[",\n\r]/.test(s) ? '"' + s.replace(/"/g, '""') + '"' : s;
  };

  const lines = [headers.join(',')];
  for (const row of rows) {
    lines.push(headers.map((h) => escape(row[h])).join(','));
  }
  return lines.join('\n');
}

注意 typeof v === 'object' 这一分支:嵌套的对象或数组没有扁平的 CSV 表达,通行的约定是把它序列化为 JSON 文本放进单元格。下文会详谈。

如何在 JavaScript 中把 CSV 转为 JSON

反过来的坑在于正确解析 CSV —— 字段可以在引号包含逗号和换行,所以不能简单地 split(',')。用一个小型状态机(或在生产环境中用 papaparse 这种库):

function csvToJson(text) {
  const rows = [];
  let row = [], field = '', inQuotes = false;
  for (let i = 0; i < text.length; i++) {
    const c = text[i];
    if (inQuotes) {
      if (c === '"' && text[i + 1] === '"') { field += '"'; i++; }
      else if (c === '"') inQuotes = false;
      else field += c;
    } else if (c === '"') inQuotes = true;
    else if (c === ',') { row.push(field); field = ''; }
    else if (c === '\n') { row.push(field); rows.push(row); row = []; field = ''; }
    else if (c !== '\r') field += c;
  }
  if (field || row.length) { row.push(field); rows.push(row); }

  const [headers, ...data] = rows;
  return data.map((cells) =>
    Object.fromEntries(headers.map((h, i) => [h, cells[i] ?? ''])));
}

如何在 Python 中互转 JSON 与 CSV

Python 标准库内置了这功能 —— 无需任何依赖。

import csv, json, io

# JSON -> CSV
rows = json.loads(json_text)
buf = io.StringIO()
writer = csv.DictWriter(buf, fieldnames=list(rows[0].keys()))
writer.writeheader()
writer.writerows(rows)
csv_text = buf.getvalue()

# CSV -> JSON
rows = list(csv.DictReader(io.StringIO(csv_text)))
json_text = json.dumps(rows, indent=2)

真正重要的边界情况

嵌套的对象与数组

CSV 是扁平的,JSON 不是。当值是对象或数组时有两个选择:把它在一个单元格里序列化为 JSON(简单、可逆),或者扁平化为多列,例如 address.cityaddress.zip(更易读,但有损且更难逆向)。如果要往返,单元格里的 JSON 更安全。

CSV 丢失类型

CSV 没有类型 —— 每个字段都是文本。从 CSV 转回 JSON 时,除非你刻意把 "1" 强转成数字,它就是字符串。要小心 007 这种值(必须保持字符串的邮编/ID),以及作为数字会丢失精度的大整数。只在往返无损时才做强转。

引号与分隔符

总是要给含逗号、引号或换行的字段加引号。某些区域设置(欧洲版 Excel 常见)使用 ; 作为分隔符 —— 如果你的 CSV 在某一列看起来不对,先检查分隔符。

键不一致

如果你的 JSON 对象并非都拥有相同的键,请用所有键的并集来构造表头,并把缺失的单元格留空 —— 不要假设第一个对象就定义了所有列。

Excel 与 UTF-8 BOM

如果你的 CSV 会在 Excel 里打开且包含非 ASCII 字符,请加上一个 UTF-8 BOM(字节 0xEF 0xBB 0xBF)。Excel 会把不带 BOM 的 UTF-8 当作老式编码读取,从而把重音字母/亚洲字符弄乱。大多数 CSV 库都有发出 BOM 的选项。

// JavaScript —— 写入 BOM,让 Excel 正确读取 UTF-8
const out = '\uFEFF' + jsonToCsv(rows);

其他分隔符(CSV vs TSV vs ;

「CSV」并不总是用逗号分隔。常见变体:

  • TSV —— Tab 分隔;当值常含逗号时更安全。
  • 欧洲版 Excel 在以逗号作小数点的区域使用 ; 作为分隔符。

如果打开后输出看起来挤在奇怪的一列里,那就是文件使用了与读取方不同的分隔符。统一一种就好(跨区域 Excel 用 , + BOM 的 CSV,工程管道用 TSV)。

面对真实世界的 CSV,请用 PapaParse

对于浏览器/Node 里来自用户的 CSV 解析,使用 PapaParse —— 它处理分隔符识别、引号字段、多行值、表头,并提供 dynamicTyping 来做数字/布尔强转。上面手写的片段对可信、简单的输入还行;面对规模,就要拿出 PapaParse。

在线把 JSON 转为 CSV —— 无需配置

对于一次性转换,可以完全跳过代码。把 JSON 贴进 fixjson 的 JSON 转 CSV 工具 并点击 To CSV,或者贴上 CSV 并点击 To JSON。它会自动处理引号、键的并集与类型强转,并完全在你的浏览器里运行 —— 不上传任何内容,这在数据包含客户记录或内部导出时很重要。

常见问题

怎样把 JSON 转为 CSV?

拿一个 JSON 对象数组,用所有键的并集构造表头,然后为每个对象写一行 —— 给任何含逗号、引号或换行的值加上引号。Python 用 csv.DictWriter,JavaScript 用一个小函数,或者直接贴到 在线工具 里。

怎样把 CSV 转为 JSON?

解析 CSV(尊重带引号的字段),把第一行视作表头,把后续每一行映射为以表头为键的对象。注意:除非你做强转,所有值都是字符串。

嵌套的 JSON 对象在 CSV 中怎么表示?

CSV 无法嵌套,所以嵌套的对象或数组通常写为单元格里的 JSON 文本,或者扁平化为点号列,如 address.city。单元格里的 JSON 是可逆的选项。

能不能在线免费把 JSON 转为 CSV?

可以 —— fixjson 的转换器 免费双向转换,完全在浏览器里,无需账号、无需上传。

相关工具与指南