贴进来的已经不是表格里那一格
做迁移的人都撞见过这一幕:Excel 里一列订单号,整块复制、粘进转换框,导出的 JSON 里末尾几位变了——110101199003072316 出来是 110101199003072320,长度仍是 18 位,只有末 2 位对不上;日期那一列整列是带引号的字符串,行数一个不缺,就是当不了数字。第一反应是「工具算错了」,但一位位数过去会发现:失真分两次,第一次在粘贴那一刻就完成了。
能进文本框的只有字符。从 Excel 复制出来的是按单元格格式渲染过的文本,工具看到的就是这串文本本身:2024/5/1、12,345.00、1.23457E+11、#N/A——都已经是 Excel 加工过的样子,工具无从也没有依据还原成日期或真实数字。
类型推断只认 4 类,其余一律落进字符串
excel-to-json 里唯一会改写单元格的步骤是类型推断,识别范围只有整数、浮点、true/false、null 四类。勾选「自动识别数据类型(数字/布尔值)」时实测如下:
| 粘贴进来的格子 | JSON 里的样子 | 发生了什么 |
|---|---|---|
2024/5/1 | "2024/5/1" | 不在识别范围,落进字符串 |
12,345.00 | "12,345.00" | 千分位当文本,只多 2 个引号 |
1.23457E+11 | "1.23457E+11" | 指数串原样保留,两种状态一样 |
#N/A | "#N/A" | 错误值也只是字符串 |
007 | 7 | 被认成整数,前导零消失 |
110101199003072316 | 110101199003072320 | 被认成整数,末 2 位改写 |
Excel 改写过的四类文本(日期串、千分位、科学计数法、错误值)不在识别范围内,原样退回成字符串;看着像整数的反倒被再加工一次——007→7、00→0、1.0→1、3.00→3、12345.67890→12345.6789、-0 写成 0,全程没有提示。裸值与带引号值混在一份数据里,下游怎么读标量,YAML 与 JSON 的标量类型改写踩过同一组坑。
会不会失真,是位数和数值一起决定的
长数字容易被理解成「位数一多就出错」,实测不是。15 位以内 3 个样本都精确;16 位是否精确要看有没有跨过 2^53(9007199254740992):同是 16 位,9007199254740991 原样保留,9007199254740993 输出成 9007199254740992。17 位起 3/3 失真,18 位普遍改掉末 2 位,19 位全 9 还进到 20 位。再往上就不是改几位的问题:22 位起 JSON 字面量换成指数形式,1000000000000000000000 输出成 1e+21,长度从 22 字符缩到 5 字符。
也有被救回来的例子:末位带一个字母(11010119900307231X),整串就不再被认成数字而保持字符串——于是同一份 JSON 里一行 number、一行 string。
想让整列保持原文,只有一个开关
能整列保住粘贴文本的只有一条:取消勾选「自动识别数据类型(数字/布尔值)」。类型推断在最前面短路,实测 48 组输入在取消勾选后全部保持字符串。边界要划清:保住的是粘贴进来那串字符,不是表格里的原始精度——勾选或取消都不会让 1.23457E+11 变回数字,也不会让 2024/5/1 变回日期。
列是按 Tab 切死的,没有分隔符可挑
切列依赖写死的 Tab,页面上没有分隔符控件,所以自动识别分隔符的说法不成立。CSV 直接粘进去,每行只算 1 列——a,b,c 得到一个元素;表头模式下整份数据塌成 1 个键。字段里带引号的 Tab 照样被切开:zhang<TAB>"xin<TAB>guo" 切出 3 格,引号只是留在格子里的字符。字段内换行会把 1 行拆成 2 行,表头模式下 2 行数据能变成 3 个对象,此后整表列位都不再对齐。
重名表头与第一列做 key:行数会缩,统计条看不出来
表头是对象输出的键名,重名就在 JSON 里塌缩:name + name + city 三列只产出 2 个键,键的值来自第 2 列(后写覆盖先写);三列同名只剩 1 个键;空列名得到一个键 "",合法而无意义;数据列比表头多时,多出的列静默丢弃。
第一列做 key 更陡:5 行只有 3 个不同 key,输出就 3 个键,2 行数据消失。统计条按对象键数显示 数据行: 3,看不出丢了行。数字形的 key 还会被重排:粘贴顺序 42、7、3,输出顺序 3、7、42。
错误提示框基本看不到
这一页的失败几乎都是静默的结构改变。54 组实测输入里「解析错误」框显示 0 次:空白类输入被提前收进空态,非空输入又至少留下 1 行,两处抛错分支走不到。单行输入在表头模式下只得到 [] 和 数据行: 0,页面照常显示,不作解释。
规模不用担心,体积要留意
没有长度上限也没有截断报错:2000 行 5 列、输入 74669 字符一次跑完,美化输出 156672 字符 / 14002 行,压缩输出 94671 字符。同一份数据 500 行时美化比压缩多 15501 字符(约 1.7 倍),表头模式又比数组多 15000 字符——键名每行重写一遍就是这笔开销。输出区那个 480px 只是显示窗口,复制走的是全量文本;要比两份输出的体积差,JSON 格式化里的美化与压缩口径可以直接套用。
转完之后建议核对这 4 处
- 最长的数字列与粘贴前逐位对:18 位以上先看末 2 位,22 位以上先看它有没有变成
1e+21这种形状。 - 键数与列数对一遍:表头有重名或空列名时,键数一定小于列数。
- 对象个数与粘贴行数对一遍:第一列做 key 与字段内换行都会让两者不等。
- 需要原样文本的列,取消勾选再跑一次,与勾选结果并排留档。
常见问题
Q:日期列能不能转成真正的时间?
不能。类型推断里没有日期分支,2024/5/1 只保持带引号的字符串,45412 这种序列号也只被当普通整数,两者都不被当日期。
Q:把类型识别关掉,就能拿回原始精度吗?
它拿回的是粘贴进来那串字符,不是单元格里的原始值。像 1.23457E+11 这种粘贴时已成指数串的文本,关掉勾选仍是指数字符串;18 位号码则只有关掉勾选才不被再改写。
Q:粘之前要不要先把 CSV 转成 Tab 分隔?
要。分隔符只有 Tab,其它符号一律整行当成 1 格,所以先在表格软件里按 Tab 复制再粘,别指望转换框认得逗号。