先把当时的情况摆出来。把人工整理的 5000 条问答存成 jsonl,逐行 json.loads 时在第 217 行报 JSONDecodeError,原文 Expecting value: line 1 column 1,肉眼看那一行和别的没区别。
排查方向其实有限,先把可能性排一排。从表格复制时带进了全角引号与全角逗号。少数情况下是行首有 BOM 或零宽字符,解析器从第一个字节就失败。
另外,某行被字段里的换行截断成两行。少数情况下是文件不是 UTF-8,中文按 GBK 解码后错位。
定位出错行的字节内容
python -c "ls=open('data.jsonl','rb').read().split(b'\n');print(ls[216][:60])"
随后把全角标点统一替换成半角
python -c "s=open('bad.txt',encoding='utf-8').read();print(s.replace('“','\"').replace('”','\"').replace(',',','))"
去掉 BOM 与零宽字符后再解析
python -c "s=open('data.jsonl',encoding='utf-8-sig').read().replace('\u200b','');print(len(s))"
末了逐行解析并收集行号而不是中断
python -c "import json;bad=[i for i,l in enumerate(open('data.jsonl',encoding='utf-8')) if not l.strip() or json.loads(l) is None];print(bad[:5])"
这次没动代码,只在配置和运行环境上找原因。
恢复的判定其实很直接。全部 5000 行都能解析成对象,坏行清单为空,字段里的中文标点保持原样。
全角引号在等宽字体里几乎看不出来,处理前先做一遍字符归一化,比逐行肉眼找快得多。拖得越久,排查成本越高,因为现场状态会被后续操作覆盖。
