CSV 转 JSON 的五个坑:前导零、引号、格子内的换行

· 5 分钟阅读 · CSV JSON · English

CSV 是"看起来最简单、实际最容易做错"的格式。麻烦不在于它复杂,而在于它有一堆没有明说的约定,而每个解析器各自猜。这五件事覆盖了绝大多数线上事故,而每一个坑都在你粘两行、把结果读回来的那一刻现形。

一、007 不是数字,N/A 也不是

CSV 里所有格子都是字符串,没有类型。很多转换器"热心"地帮你判断类型,于是 007 变成 7、1e5 变成 100000、N/A 变成 null、2026-10-04 变成某个时区的日期。这一步看起来无害,实际把信息毁掉了:下一个程序分不清"丢了前导零的邮编"和"本来就是数字 7"。

所以规则很简单:转换阶段一律保留字符串,类型是业务层的事。CSV 转 JSON就是这样——007 出来还是 "007",要数字请你自己 Number()。

二、引号只有在格子开头才算数

RFC 4180 的判定很机械:一格的第一个字符是 ",它才是引号格;出现在中间的引号只是数据。所以 "abc"def 解出 abc"def,而不是在第二个引号处提前结束。同理,连续两个引号表示一个引号——he said ""hi"" 解出 he said "hi"。

这套规则解释了为什么 CSV 不能用 split(",") 加 split("\n") 打发:引号里可以合法地包含逗号、换行,甚至一整段地址。手工处理十次有九次会在这里翻车。

把两种读法摆在同一张表里,对着常见的那几种片段看。结果都写成"最后得到哪几行",每行再写成格子的列表:

文件里的这一段 按 , 和 \n 直接切 按 RFC 4180 读
"1,2 Street",7 [['"1', '2 Street"', '7']]——1 行 3 格 [['1,2 Street', '7']]
"a\nb",9,换行在引号里 [['"a'], ['b"', '9']]——2 行 [['a\nb', '9']]——1 行
"abc"def [['"abc"def']],两个引号都留着 [['abc"def']]
文件结尾带 \n,比如 a,b\n [['a', 'b'], ['']] [['a', 'b']]

前两行是悄悄改坏了数据的那种,后两行只在把结果读回来时才显出不对。

三、格子里的换行会毁掉你的行数

id,name,note
1,"王小明","备注第一行
备注第二行"
2,李华,

上面这段是两条记录,不是三行。note 那格里存着带换行的文本,行数以 \n 计数就会多出一条不存在的记录。反过来,写 CSV 的时候这种格子必须加引号,换行用 CRLF(\r\n)——因为 Excel 期待的是它。

还有一个细节:文件结尾那个换行只是让最后一行结束,不是又多一条空记录;而开头的空行会被跳过(勾了表头时,它本会顶替真正的列名)。

四、行长短不齐时,谁被丢掉

真实导出的 CSV 经常参差不齐。JSON 表达不了"这一列当时不在",所以只能有明确的处理口径,而且必须说出来:

  • 格子少了的行:缺的键补 null,宁可显式地空,也不让每条记录的形状各不相同;
  • 格子多了的行:JSON 根本装不下,所以结果里会点名第几行、几个格、掉的那格开头是什么,不做静默截断——这条提示存在的全部意义就是别让你三天后才发现;
  • 表头重名:一个键只能装一个值,会合并,并在补充说明里讲清楚;
  • 表头里有空格子:那列按位置叫 第3列 之类的名字,哪几列被这样命名会列出来;
  • 不勾"第一行是表头":输出是数组的数组,这是唯一能保住参差表格形状的结构。

五、分隔符经常不是逗号

“我的文件全挤成一列"几乎都是分隔符和文件不匹配。欧洲的表格软件默认导出分号分隔(因为逗号是当地的小数点),数据库客户端导出的是制表符,管道符 | 在某些日志导出里也见得到。CSV 与 JSON 互转把这四种都做成按钮,点一下格子数立刻跟着变。

至于乱码:这里不修。你粘进文本框的那一刻,它已经是一串 Unicode 了——如果原来就该按 GBK 解码却没解对,错着进来的只能错着出去。回到产生它的那个软件,另存为 UTF-8。

反过来,JSON 转 CSV

JSON 表格有三种形状,都得能写出去:对象数组(表头取所有键的并集,按第一次出现的顺序排,某条记录缺的键写成空格)、数组套数组(逐行直写,不生成表头,因为没有键名可用)、单个对象(两行:键名当表头、值当数据行)。

格子里嵌着对象或数组的,按 JSON 文本写进那一格而不摊平——“子对象该摊成哪几列"没有公认答案,宁可让你在单元格里看到花括号,也不编一个规则假装它不存在。

什么时候别用浏览器转

解析上限是 200,000 字符、5,000 行,超出会在提示里写明少了多少。这个体量就该拆分文件或者用真正的流式工具:让一个标签页抱着整个文件字符串,既慢又容易崩,不是合适的工具。三万条记录的正确解法是 pandas、jq 或数据库的导入命令。

顺带一句隐私口径:这类换算全在页面脚本里完成,你粘贴的数据不会离开这台设备——这也是它敢于只适合"小到能粘进文本框"的数据的原因。

相关问题

为什么转出来的 JSON 里全是引号? 因为 CSV 没有类型,保留字符串是唯一不丢信息的做法。

Excel 打开 CSV 就丢了前导零怎么办? 那是 Excel 在导入时自行猜类型,跟转换无关。用"数据 → 从文本导入"并把列指定为文本,或者干脆用表格软件之外的路径处理。

表头里有中文能用吗? 能,JSON 的键什么字符串都收。真正要注意的是别在 Excel 里另存成 ANSI 编码。

能不能顺手做去重、排序、转成 SQL 的 IN (...)? 那几个是不同形状的活,用列表转换:按行、按逗号、数组、IN 列表之间互转。

微信
微信
支付宝
支付宝