模型 JSON 里有孤立代理字符,为什么能读取却写不成 UTF-8
原始 JSON 文件全是 ASCII,json.loads 也没有报错,为什么最终写成 UTF-8 时失败?一种原因是字符串通过转义带进了孤立代理码点。字节解码、JSON 转义解释和 Unicode 编码是三个阶段;前两步完成,不代表最后一步一定有合法编码结果。
能读入的是转义,不是有效字符保证
附件把 \ud83d\ude00 作为合法代理对,与单独的 \ud83d、单独的 \ude00 放在不同样本里。正常中文及合法成对表示应通过;孤立高代理与低代理应拒收。这里讨论的是字符串码点,不是字体是否显示一个方框,也不是 UTF-8 网络字节被切开的问题。
Python JSON 文档提示对这类代理项的兼容行为。客户端应在准备落盘或发送前执行严格 UTF-8 编码检查,逐字段找到不能编码的值。对象键也属于字符串,不能只查字段值。错误记录保留字段路径和转义后的码点表示,避免打印错误信息时再次触发同样的编码异常。
保留定位,不静默删字
示例检查器递归遍历列表和对象,路径使用明确的字段与索引序列。问题位于 items 的第一项文本时,应能回到这一项,而不是只告诉用户“存在非法 Unicode”。正常项原样往返,不因检查而做大小写、全半角或 Unicode 归一化;编码合法与文本归一是不同需求。
失败反例是 errors='ignore'。它确实可能让文件写出,但会直接删除无法编码的内容,导致引文、标识符或证据不再完整。replace 也会改变原文,除非合同明确允许展示替代字符,否则不能把这种结果当作成功数据保存。
留样要避免制造第二次故障
如果需要保存坏响应,应保存原始接收字节或经过 ASCII 转义的诊断结构,而不是将已含孤立代理项的内存字符串直接写入 UTF-8 日志。附件 JSON 使用转义形式,所以文件本身可安全传递;检查器读取后才产生待检查的内存值。诊断必须同时说明哪一个阶段失败,避免维护者误以为服务器发送了无效 UTF-8 字节。
本例不尝试自动把相邻字符串中的高低代理拼成字符,也不将替换字符反推回原意。若上游协议分段导致错误,应在真正负责分段的层修复,不能用内容层猜测补救。本文只验完整 JSON 文档中的字符串边界。
上线前还应确认数据库、消息队列和导出程序使用一致的编码政策。入口检查通过只是避免这一类非法码点继续流动;可显示、可搜索和符合业务字符集合仍需各自规则。合成样本通过不表示真实模型已经测试过,正文与检查器都只声明本地编码验证。
配套文件与依据
本文的合成输入和参考结果可下载独立样本 a011.json,离线检查器 a011.py与样本放在同一目录后运行。检查器不调用模型接口。 使用 Python 3.12 或兼容版本,将上述文件下载到同一目录,执行 python a011.py。
留言讨论
评论发布后会被人工复核,违规内容将被删除。
如果发表没有反应,可以前往联系我们告诉我们。