← 返回博客 / 数据格式 / JSON 转 CSV 完全指南

📊 JSON 转 CSV 完全指南:数据结构、嵌套展开与实战技巧

2026-07-17 · 约 12 分钟

「PM 给我丢了一个 JSON 文件,说『帮导出个 Excel』」—— 这种场景做过数据分析的应该都懂。JSON 在程序员的世界里很自然,但到了业务同事手里,转成 CSV 打开才是真正的「可读」格式。

这篇文章覆盖 JSON 转 CSV 的所有常见场景:简单数组怎么转、嵌套对象怎么展开、中文乱码怎么处理、Python/JavaScript/在线工具分别怎么搞。

JSON 和 CSV 的区别

简单说:

这两种格式天然不匹配。JSON 转 CSV 的本质是 「把树拍平」

特性JSONCSV
数据结构层级嵌套扁平表格
可读性(人类)中等高(Excel 可直接打开)
类型支持字符串、数字、布尔、null、对象、数组全是文本
文件大小键重复,偏大更紧凑
典型场景API 传输、配置文件数据分析、Excel 导入/导出

一、最简单的场景:数组中的简单对象

最常见的 JSON 结构是一组相同字段的对象数组:

[
  { "name": "张三", "age": 28, "city": "北京" },
  { "name": "李四", "age": 32, "city": "上海" },
  { "name": "王五", "age": 25, "city": "深圳" }
]

转成 CSV 很简单,取所有键作为表头,每个对象一行:

name,age,city
张三,28,北京
李四,32,上海
王五,25,深圳

这种直接用 Python 的 csv 模块或者任意在线工具就能搞定。

💡 注意:CSV 没有类型系统。数字 28 和字符串 "28" 在 CSV 里看着一样。Excel 打开后可能会自作主张把数字变科学计数法(比如长数字 ID)。一个常用技巧是在数字前加一个 \t 前缀强制当文本处理。

二、嵌套对象怎么处理?

实际场景中 JSON 几乎不会这么工整。最常见的难题就是 嵌套 JSON 对象

[
  {
    "id": "U001",
    "name": "张三",
    "address": {
      "province": "浙江",
      "city": "杭州",
      "district": "西湖区"
    },
    "contact": {
      "email": "zhangsan@example.com",
      "phone": "13800138000"
    }
  },
  {
    "id": "U002",
    "name": "李四",
    "address": {
      "province": "广东",
      "city": "深圳",
      "district": "南山区"
    },
    "contact": {
      "email": "lisi@example.com"
    }
  }
]

这种结构不能直接转。常见的策略是 展平(Flatten):用点号连接嵌套层级作为列名。

idnameaddress.provinceaddress.cityaddress.districtcontact.emailcontact.phone
U001张三浙江杭州西湖区zhangsan@example.com13800138000
U002李四广东深圳南山区lisi@example.com

注意第二行的 contact.phone 是空的——JSON 中缺失的字段在 CSV 里就是空值。

Python 实现:嵌套展开

import json, csv, sys

def flatten(obj, parent_key='', sep='.'):
    items = []
    for k, v in obj.items():
        new_key = f"{parent_key}{sep}{k}" if parent_key else k
        if isinstance(v, dict):
            items.extend(flatten(v, new_key, sep=sep).items())
        else:
            items.append((new_key, '' if v is None else v))
    return dict(items)

data = json.load(sys.stdin)
with open('output.csv', 'w', newline='', encoding='utf-8-sig') as f:
    writer = csv.DictWriter(f, fieldnames=flatten(data[0]).keys())
    writer.writeheader()
    for item in data:
        writer.writerow(flatten(item))

encoding='utf-8-sig' 这个参数加了 BOM 头,Excel 打开中文就不会乱码了。

三、数组字段怎么处理?

JSON 里的数组字段更难搞。比如这个:

[
  {
    "order_id": "ORD001",
    "items": ["苹果", "香蕉", "牛奶"]
  },
  {
    "order_id": "ORD002",
    "items": ["面包", "鸡蛋"]
  }
]

数组不能直接塞进一个格子——虽然 CSV 规范允许单元格内带逗号(加引号),但这样会破坏数据的可分析性。

常见方案有三种:

  1. 用分隔符合并:items → "苹果|香蕉|牛奶",适合简单场景
  2. 转多行:每个 item 单独成行,order_id 重复,适合数据库导入
  3. 拆成多列:items_1, items_2, items_3...,但数组长度不一的话会有很多空列
方案输出适用场景
合并ORD001,"苹果|香蕉|牛奶"快速查看
多行ORD001,苹果 / ORD001,香蕉 / ORD001,牛奶关系型数据库导入
多列ORD001,苹果,香蕉,牛奶固定长度的简单数组

四、中文字符编码——最容易踩的坑

JSON 转 CSV 最大的坑不是转换逻辑,而是 编码

直接生成的 CSV 用 UTF-8 编码。Excel(尤其是 Windows 上的 Excel)默认用 GBK 或 ANSI 打开文件,结果中文全变成乱码。

⚠️ 解决方案:保存 CSV 时使用 UTF-8 with BOM(utf-8-sig)。这样 Excel 能正确识别编码。Python 里就是 encoding='utf-8-sig',JavaScript 里加 \uFEFF 前缀。

用 JavaScript 在浏览器端生成并下载带 BOM 的 CSV:

function downloadCSV(data) {
  const headers = Object.keys(data[0]);
  const csv = [
    headers.join(','),
    ...data.map(row =>
      headers.map(h => JSON.stringify(row[h] ?? '')).join(',')
    )
  ].join('\n');
  const blob = new Blob(['\uFEFF' + csv], { type: 'text/csv;charset=utf-8;' });
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = 'data.csv';
  a.click();
}

五、JavaScript(浏览器端)一键转换

如果不想装 Python,浏览器里也能搞定。配合在线工具或者自己写个简单的 HTML 页面:

function jsonToCsv(jsonArray, flattenNested = true) {
  if (!Array.isArray(jsonArray) || jsonArray.length === 0) {
    return '';
  }

  // 展平嵌套
  const flatten = (obj, prefix = '') => {
    const result = {};
    for (const [key, value] of Object.entries(obj)) {
      const newKey = prefix ? `${prefix}.${key}` : key;
      if (flattenNested && value !== null && typeof value === 'object' && !Array.isArray(value)) {
        Object.assign(result, flatten(value, newKey));
      } else if (Array.isArray(value)) {
        result[newKey] = value.join('|');
      } else {
        result[newKey] = value === null ? '' : String(value);
      }
    }
    return result;
  };

  const flatData = jsonArray.map(item => flatten(item));
  const headers = [...new Set(flatData.flatMap(Object.keys))];
  const lines = [headers.join(',')];

  for (const row of flatData) {
    const values = headers.map(h => {
      const val = row[h] ?? '';
      return /[,"\n]/.test(val) ? `"${val.replace(/"/g, '""')}"` : val;
    });
    lines.push(values.join(','));
  }

  return lines.join('\n');
}

六、在线工具一步解决

如果是偶尔用一次,写代码就大炮打蚊子了。直接用我们的免费在线工具:

🧰 JSON 转 CSV 在线工具

支持嵌套展开、自定义分隔符、含 BOM 下载,数据仅在浏览器本地处理

开始转换 →

粘贴 JSON → 点转换 → 下载 CSV。三步搞定。

七、一些你可能会遇到的复杂情况

情况 1:JSON 根节点不是数组?

很多 API 返回的是这种结构:

{
  "status": "success",
  "count": 3,
  "data": [
    { "name": "张三", "score": 95 },
    { "name": "李四", "score": 87 }
  ]
}

需要先取出 data 数组再转。在线工具通常可以手动操作,代码里就是 json['data']

情况 2:JSON 中 null 值怎么处理?

统一处理为空字符串。不要写 "null" 字符串,否则 Excel 里会把这个当一个叫 "null" 的文本值。

情况 3:CSV 中的特殊字符

如果字段值包含逗号、换行符或引号:

基本所有正经 CSV 工具都会自动处理这个。

情况 4:大文件转换

几万行的 JSON 浏览器端转换可能会卡。方案:

总结

JSON 转 CSV 听起来简单,但细节挺多:

如果只是偶尔用,在线工具 是最省事的选择。如果是日常工作需要频繁转换,上面的 Python 或 JavaScript 代码可以直接用起来。