打印格式化JSON时字符串插入意外字符\327的问题排查
问题解析:希伯来语JSON格式化后出现\327转义符的原因及解决方法
一、\327是什么?
\327是八进制转义序列,对应十进制ASCII码215(计算方式:3×64 + 2×8 +7 = 215),对应Unicode字符U+00D7(乘号×)。这里的\327并非业务需要的字符,是编码转换错误导致的乱码。
二、为什么会出现这个问题?
问题根源在JSONSerialization的序列化流程:
- 服务器返回的原始Data是正确的UTF-8编码,直接转String(raw模式)时希伯来语显示正常;
- 但经过
JSONSerialization.jsonObject(with:)解析成内存对象,再调用data(withJSONObject:options:)转回Data时,系统API对希伯来语这类非ASCII多字节UTF-8字符的处理出现异常——错误地将希伯来语字符的某个UTF-8字节(比如0xD7,八进制正好是327)转成了八进制转义符\327,最终转成String时就出现了干扰字符。
这种问题多和iOS版本的JSONSerialization实现bug相关,尤其是混合使用.prettyPrinted和.withoutEscapingSlashes选项时更容易触发。
三、解决方案
方案1:改用JSONEncoder替代JSONSerialization
JSONEncoder对UTF-8编码的处理更稳定,能规避系统旧API的编码bug:
extension Data { var prettyJSON: String? { do { let jsonObject = try JSONSerialization.jsonObject(with: self) let encoder = JSONEncoder() if #available(iOS 13.0, *) { encoder.outputFormatting = [.prettyPrinted, .withoutEscapingSlashes] } else { encoder.outputFormatting = .prettyPrinted } let prettyData = try encoder.encode(jsonObject) return String(data: prettyData, encoding: .utf8) } catch { return nil } } }
方案2:使用第三方JSON库(如SwiftyJSON)格式化
第三方库的编码逻辑更健壮,能彻底规避系统API的问题:
// 先引入SwiftyJSON库 extension Data { var prettyJSON: String? { let json = JSON(self) return json.rawString(.utf8, options: .prettyPrinted) } }
方案3:临时修复(治标不治本)
如果暂时无法修改序列化逻辑,可以在生成格式化字符串后手动清理错误转义:
guard let pretty = pretty else { return nil } return String(data: pretty, encoding: .utf8)?.replacingOccurrences(of: "\\327", with: "")
验证
修改后测试日志输出,确认希伯来语字符串显示正常,复制后的JSON能在其他系统正常解析。
内容的提问来源于stack exchange,提问作者Arik Segal
相关产品推荐
相关产品推荐

