从Tcl传递含em破折号的JSON字符串到浏览器解析失败如何解决?
问题根因
- 手动拼接JSON未做特殊字符转义:直接把
$text_content拼到JSON字符串中,没有转义JSON规范要求处理的特殊字符(包括双引号、反斜杠、控制字符,未正确编码的非ASCII字符也会触发解析错误),这是报错的直接原因。 - HTTP头格式错误:
Content-Type字段的字符集声明写法错误,正确格式为charset=utf-8,不是charset: utf-8。 - Content-Length计算错误:用
string length得到的是Unicode字符数量,但后续用二进制通道发送UTF-8内容时,非ASCII字符(比如你遇到的em破折号)会占用多个字节,长度不匹配会导致浏览器读取到截断或异常内容。 - 字符串编码处理错误:直接把Tcl的Unicode字符串写入二进制通道,没有显式转成UTF-8字节序列,会导致字符编码错乱。
- 缺失HTTP头与正文的分隔空行:HTTP协议要求响应头和正文之间必须有一个空行,你的代码中遗漏了这个分隔符,也会导致解析异常。
修复方案
1. 使用标准JSON库生成合法JSON
不要手动拼接JSON,推荐用tcllib的json包自动处理转义逻辑,避免出错:
# 提前加载json包 package require json::write # 生成JSON的逻辑替换为 set result [json::write object result $text_content]
如果不想引入额外依赖,至少要手动转义$text_content中的特殊字符:把\替换为\\、"替换为\"、所有控制字符替换为对应的转义序列。
2. 修正服务端响应逻辑
proc GetSQL {sock} { chan flush $sock set sql {select text_content from tablename where conditions ... } set text_content "" dbt eval $sql { # 此处根据实际返回条数处理,示例默认仅返回1条结果 } # 生成合法JSON package require json::write set result [json::write object result $text_content] # 显式转成UTF-8字节序列,计算正确的字节长度 set result_utf8 [encoding convertto utf-8 $result] set content_length [string length $result_utf8] # 构造响应头,补充头和正文的分隔空行 set headers "" append headers "HTTP/1.1 200 OK\n" append headers "Content-Type: application/json; charset=utf-8\n" append headers "Content-Length: $content_length\n" append headers "Connection: Keep-Alive\n" append headers "\n" # 先发送响应头,再切换二进制模式发送正文 puts $sock $headers chan configure $sock -translation binary puts -nonewline $sock $result_utf8 chan flush $sock }
额外校验点
确认SQLite的text_content字段存储的是正确解码的Unicode字符串,没有重复编码的UTF-8字节序列,避免二次编码导致字符错乱。
内容的提问来源于stack exchange,提问作者Gary
相关产品推荐
相关产品推荐

