← 全部文章

如何把 CSV 与 XML 转成 JSON

在 JavaScript、Python 和浏览器里把 CSV 与 XML 转成 JSON。涵盖 array-of-objects 映射、XML 属性处理、以及类型推断的坑。

CSV 和 XML 到处都是 —— 表格导出、老 API、企业级 feed —— 但大多数现代代码想要的是 JSON。一旦你理解了映射规则和那些坑(CSV 里的一切都是字符串;XML 的属性和重复元素需要特殊处理),转换就很直接。本指南覆盖 JavaScript、Python 和浏览器里两个方向的转换。

范围: 本文是把 CSV → JSON 和 XML → JSON 放在一起讲的宽泛的 how-to。如果你需要专门讲 XML —— 属性、文本节点、重复元素、命名空间这些细节 —— 请看 XML 到 JSON 的转换:属性、文本节点、数组与命名空间。反方向请见 JSON 到 XML

把 CSV 转成 JSON

一份 CSV 文件是一行行的逗号分隔值,通常带一行表头。自然的 JSON 表示是一个对象数组,每行一个对象,用表头做键:

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

注意每个值都是字符串 —— CSV 没有类型。把 "1" 转成数字、把 "true" 转成布尔值,是你必须有意识地做的另一步类型转换。

在 JavaScript 里把 CSV 转成 JSON

对可信的、简单的 CSV,你可以手动 split —— 但真实世界的 CSV 有带引号的字段、字段里有逗号和换行,所以生产环境用一个像样的 parser,比如 papaparse

// 最小 parser —— 只对简单、无引号的 CSV 安全
function csvToJson(csv) {
  const [header, ...rows] = csv.trim().split('\n');
  const keys = header.split(',');
  return rows.map((row) => {
    const values = row.split(',');
    return Object.fromEntries(keys.map((k, i) => [k, values[i]]));
  });
}

// 生产 —— 处理引号、内嵌逗号、换行
import Papa from 'papaparse';
const result = Papa.parse(csvText, { header: true, dynamicTyping: true });
// dynamicTyping 会自动把 "1" → 1、"true" → true

在 Python 里把 CSV 转成 JSON

import csv, json

with open('data.csv', newline='') as f:
    rows = list(csv.DictReader(f))   # 用表头做键的 dict 列表

print(json.dumps(rows, indent=2))

把 XML 转成 JSON

XML 更棘手,因为它有 JSON 没有的概念:属性、文本节点、以及「单次出现 vs 重复出现」的元素。没有唯一「正确」的映射,挑一个约定并一致地应用就行。

<!-- XML -->
<user id="1">
  <name>Ada</name>
  <role>admin</role>
  <role>editor</role>
</user>
// 一个常见的 JSON 映射
{
  "user": {
    "@id": "1",                    // 属性,前缀 @
    "name": "Ada",                 // 单个子元素 → 值
    "role": ["admin", "editor"]    // 重复子元素 → 数组
  }
}

在 JavaScript 里把 XML 转成 JSON

import { XMLParser } from 'fast-xml-parser';

const parser = new XMLParser({ ignoreAttributes: false, attributeNamePrefix: '@' });
const obj = parser.parse(xmlString);
// 在浏览器里你也可以用 DOMParser 然后手动遍历节点树。

在 Python 里把 XML 转成 JSON

import xmltodict, json

doc = xmltodict.parse(xml_string)   # 属性会变成 "@name" 键
print(json.dumps(doc, indent=2))

要小心的映射坑

  • 类型会丢。 CSV 和 XML 的值过来都是字符串。明确地强制转换数字和布尔值 —— 别假定 parser 已经替你做了。
  • 单个 vs 重复元素。 一个 <role> 变成一个值;两个则变成数组。决定某个字段是不是要永远当数组,免得让消费方惊讶。
  • 属性 vs 子元素。选一个前缀约定(常见的是 @)并写进文档。
  • 空值和空白。 空的 XML 元素和 CSV 末尾的逗号可能根据 parser 不同而产生 null"" 或者干脆缺键。

BOM 与编码的怪癖

从 Excel 和某些 Windows 工具导出的文件会以 UTF-8 BOM 开头(0xEF 0xBB 0xBF)。解析前先把它去掉,不然你的第一个表头/元素名会悄悄带着它。RFC 8259 禁止在 JSON 开头放 BOM,所以你写的转换器应该把它从输入里移除,而不是抄到输出里。

TSV vs CSV(以及其他分隔符)

「CSV」并不总是逗号分隔。制表符分隔值(TSV)在工程管道里很常见,因为 tab 几乎不会出现在字段值里,可以省掉一整套引号机制。欧洲版 Excel 导出经常用 ;。如果你看到输出挤成一列怪样子,那就是文件用的分隔符和你 parser 期待的不一样 —— 换一下分隔符,或者用一个能自动探测的库。

XML 命名空间

XML 元素可以带命名空间前缀(比如 <soap:Envelope>),由 xmlns 声明绑定。JSON 没有命名空间概念,所以大多数转换器会走三条路之一:把前缀保留在键里("soap:Envelope")、把它去掉、或者把 xmlns 声明存成 @xmlns:* 属性。保留前缀是唯一无损的选择。要看深入讲解,请见 XML 到 JSON 的转换

校验并格式化结果

转换之后,确认输出格式良好、可读:

常见问题

怎么把 CSV 转成 JSON?

把 CSV 解析成行,然后每行映射成一个用表头做键的对象 —— Python 用 csv.DictReader,JavaScript 用像 papaparse 这样的库。记住所有值最初都是字符串;类型转换你自己做。

为什么我 CSV 转出来的 JSON 里全是字符串?

CSV 是无类型的 —— 每个字段都是文本。打开类型自动转换(比如 papaparse 的 dynamicTyping),或者在解析之后明确地转换数字和布尔值。

把 XML 转成 JSON 时怎么处理 XML 属性?

大多数转换器会把属性映射成带前缀的键,比如 @(如 @id)。选一个约定并一致地应用,下游代码才知道去哪里找。

为什么我的 XML 转 JSON 输出有时是对象有时是数组?

单个子元素映射成值;重复元素映射成数组。如果消费方期待一致的形状,请把 parser 配置成对某些元素始终当数组处理。

在你的浏览器里转换、校验和格式化