CSV 转 JSON:实用指南

CodeKit
csvjson数据转换

为什么要将 CSV 转换为 JSON?

CSV(逗号分隔值)和 JSON(JavaScript 对象表示法)是两种最常见的数据格式,但它们的用途不同。CSV 适合电子表格和表格数据,而 JSON 擅长表示结构化的层次数据。在数据处理、API 开发和配置管理中,两者之间的转换是一项常见任务。

CSV 与 JSON:快速对比

特性CSVJSON
结构扁平、表格状层次化、可嵌套
数据类型全部为字符串字符串、数字、布尔值、null
表头第一行(可选)每个对象中的键
嵌套原生不支持完全支持
可读性好(小数据集)好(尤其是格式化后)
文件大小较小较大(重复的键)
解析速度较快稍慢

基本转换

以下是一个简单的 CSV 文件及其对应的 JSON:

CSV:

name,age,city
Alice,30,New York
Bob,25,San Francisco
Charlie,35,Chicago

JSON:

[
  { "name": "Alice", "age": 30, "city": "New York" },
  { "name": "Bob", "age": 25, "city": "San Francisco" },
  { "name": "Charlie", "age": 35, "city": "Chicago" }
]

注意在 JSON 中,age 值可以是真正的数字而非字符串——JSON 保留数据类型,而 CSV 将所有内容视为文本。

编写 CSV 转 JSON 转换器

简单实现

function csvToJson(csv) {
  const lines = csv.trim().split('\n');
  const headers = lines[0].split(',');

  return lines.slice(1).map(line => {
    const values = line.split(',');
    const obj = {};
    headers.forEach((header, index) => {
      obj[header.trim()] = values[index]?.trim() || '';
    });
    return obj;
  });
}

const csv = `name,age,city
Alice,30,New York
Bob,25,San Francisco`;

console.log(JSON.stringify(csvToJson(csv), null, 2));

这在简单情况下可以工作,但现实中的 CSV 数据很少这么干净。

处理常见的 CSV 陷阱

1. 包含逗号的引号字段

包含逗号的 CSV 字段必须用引号包裹:

name,description
"Smith, John","A developer, designer"

简单的 split(',') 会破坏这种数据。你需要一个正确的 CSV 解析器:

function parseCSVLine(line) {
  const result = [];
  let current = '';
  let inQuotes = false;

  for (let i = 0; i < line.length; i++) {
    const char = line[i];
    if (char === '"') {
      if (inQuotes && line[i + 1] === '"') {
        current += '"';
        i++; // 跳过转义引号
      } else {
        inQuotes = !inQuotes;
      }
    } else if (char === ',' && !inQuotes) {
      result.push(current);
      current = '';
    } else {
      current += char;
    }
  }
  result.push(current);
  return result;
}

2. 不同的分隔符

并非所有 CSV 文件都使用逗号。制表符分隔值(TSV)和分号分隔文件也很常见,尤其是在使用逗号作为小数点的欧洲地区。

function csvToJson(csv, delimiter = ',') {
  const lines = csv.trim().split('\n');
  const headers = parseCSVLine(lines[0], delimiter);

  return lines.slice(1).map(line => {
    const values = parseCSVLine(line, delimiter);
    const obj = {};
    headers.forEach((header, index) => {
      obj[header.trim()] = values[index]?.trim() || '';
    });
    return obj;
  });
}

// 制表符分隔数据
const tsvData = csvToJson(tsvContent, '\t');

// 分号分隔数据
const csvData = csvToJson(csvContent, ';');

3. 类型推断

CSV 值都是字符串,但你通常希望 JSON 中有数字、布尔值或 null:

function inferType(value) {
  if (value === '' || value === 'null' || value === 'NULL') return null;
  if (value === 'true' || value === 'TRUE') return true;
  if (value === 'false' || value === 'FALSE') return false;
  if (!isNaN(value) && value.trim() !== '') return Number(value);
  return value;
}

// 在转换过程中应用类型推断
headers.forEach((header, index) => {
  obj[header.trim()] = inferType(values[index]?.trim() || '');
});

处理嵌套数据

CSV 本质上是扁平的,但有时你需要嵌套的 JSON 结构。一种常见的约定是在表头中使用点号表示法:

user.name,user.email,address.city,address.zip
Alice,alice@example.com,New York,10001

转换为:

[
  {
    "user": { "name": "Alice", "email": "alice@example.com" },
    "address": { "city": "New York", "zip": 10001 }
  }
]
function setNestedValue(obj, path, value) {
  const keys = path.split('.');
  let current = obj;
  for (let i = 0; i < keys.length - 1; i++) {
    if (!current[keys[i]]) current[keys[i]] = {};
    current = current[keys[i]];
  }
  current[keys[keys.length - 1]] = value;
}

大文件处理建议

对于大型 CSV 文件(数百万行),请注意以下几点:

  • 流式处理:不要将整个文件加载到内存中,逐行处理
  • 批量写入:分块写入 JSON 输出,而不是构建一个巨大的数组
  • 内存占用:100 MB 的 CSV 文件转换为 JSON 后可能扩展到 200+ MB,因为键名会重复
// 流式处理方式(Node.js)
const readline = require('readline');
const fs = require('fs');

async function convertLargeCSV(inputPath, outputPath) {
  const stream = fs.createReadStream(inputPath);
  const rl = readline.createInterface({ input: stream });
  const output = fs.createWriteStream(outputPath);

  output.write('[\n');
  let headers = null;
  let first = true;

  for await (const line of rl) {
    if (!headers) {
      headers = line.split(',');
      continue;
    }
    const values = line.split(',');
    const obj = {};
    headers.forEach((h, i) => obj[h] = values[i]);

    if (!first) output.write(',\n');
    output.write(JSON.stringify(obj));
    first = false;
  }
  output.write('\n]');
}

使用 CodeKit 工具

无需编写代码即可快速转换,使用这些 CodeKit 工具:

  • CSV 转 JSON:粘贴 CSV 数据即可获得即时 JSON 输出,支持自定义分隔符和类型推断
  • JSON 格式化:格式化和验证 JSON 输出,提高可读性

两个工具都完全在浏览器中运行——数据不会发送到任何服务器。

总结

将 CSV 转换为 JSON 是一项看似简单但有许多边界情况的任务。引号字段、不同分隔符、类型推断和嵌套结构都需要仔细处理。无论你是自己编写转换器还是使用工具,理解这些细节都能帮助你避免数据损坏,构建更健壮的数据处理流程。

准备好转换数据了吗?试试 CodeKit 上的 CSV 转 JSON 转换器JSON 格式化工具,即时在浏览器中完成转换。