必须用json.stringify()才能发送json,因websocket.send()仅接受字符串、arraybuffer等四类类型,不支持原始对象;直接传对象会变成"[object object]",导致后端解析失败。

必须用 JSON.stringify() 才能发 JSON
WebSocket 的 send() 方法不接受原始对象,直接传 {type: "login", user: "alice"} 会变成 [object Object] 发出去,服务端收到的就是个无意义字符串。唯一可靠的方式是手动序列化。
常见错误现象:
- 前端控制台没报错,但后端解析失败,
JSON.parse()抛SyntaxError: Unexpected token o in JSON at position 1 - 消息内容里出现
undefined或空字段,因为对象里有未定义值,JSON.stringify()会静默丢弃它们
实操建议:
用于端到端视频本地化流程的轻量编排器,路由至四个专注子技能——/wjs-transcribing-audio、/wjs-translating-subtitles...
- 发送前始终用
JSON.stringify(data),别依赖框架或库自动处理 - 如果需要过滤空值或控制精度(比如时间戳转 ISO 字符串),先处理对象再序列化,而不是靠
replacer参数硬塞逻辑 - 调试时可临时加一层校验:
const jsonStr = JSON.stringify(data); console.assert(jsonStr !== "[object Object]", "data 未被正确序列化"); socket.send(jsonStr);
socket.send() 只认字符串,不是“支持 JSON”
文档里说 WebSocket “支持发送 JSON”,其实是种简略说法。底层只认四种类型:USVString、Blob、ArrayBuffer、ArrayBufferView。JSON 对象不属于其中任何一种——它必须先变成字符串。
性能与兼容性影响:
- 小消息(JSON.stringify() 没压力;但高频发送大对象(如含 base64 图片字段)时,序列化本身会占主线程时间,可能卡 UI
- IE10+、所有现代浏览器都支持
JSON.stringify(),无需 polyfill;但若对象含Date、undefined、function,默认行为会丢数据或报错
实操建议:
- 避免在
send()前拼接字符串再JSON.parse()再JSON.stringify()—— 这是典型冗余操作 - 不要给
JSON.stringify()传函数或循环引用对象,会直接抛异常 - 如需统一处理日期,提前转成字符串:
data.timestamp = new Date().toISOString()
接收端必须用 JSON.parse(),且得加错误捕获
前端收到的 event.data 永远是字符串(除非你设了 binaryType = "arraybuffer")。不做 JSON.parse() 就直接当对象用,运行时会出 TypeError: Cannot read property 'type' of undefined。
容易踩的坑:
- 服务端偶尔返回非 JSON 的调试信息(如
"pong"或错误提示文本),前端没做类型判断就直接JSON.parse(),导致整个onmessage流程中断 - 网络传输中 JSON 字符串被截断(尤其弱网下),
JSON.parse()报Unexpected end of JSON input,不 catch 就静默失败
实操建议:
- 始终把
JSON.parse()包在try/catch里:ws.onmessage = (e) => { try { const data = JSON.parse(e.data); handleIncomingMessage(data); } catch (err) { console.warn("无效 JSON 收到:", e.data, err); }} - 约定服务端返回格式统一加
type字段,前端先检查typeof data === "object" && data?.type再往下走 - 不要在
catch里重连或刷新页面——单条消息损坏不该触发全局状态变更
别在 JSON 字符串里嵌套 JSON 字符串
这是新手高发错误:把一个已序列化的字符串再包进对象,二次 stringify。例如:
const inner = JSON.stringify({id: 123});const outer = JSON.stringify({payload: inner}); // ❌ 错误:payload 字段值是带双引号的字符串结果是 {"payload":"{\"id\":123}"},后端解析后得到的是字符串而非对象。
正确做法永远只 stringify 一次原始对象:
- 要传结构化数据,就构造对象再 stringify:
JSON.stringify({payload: {id: 123}}) - 真要动态拼 JSON 字符串(极少见),用
JSON.parse()先还原,再合并对象,最后 stringify - 服务端如果返回的是 JSON 字符串(不是对象),说明它已经多做了一层序列化,前端应只 parse 一次,且需和服务端对齐设计
复杂点在于:这种嵌套问题往往在前后端联调时才暴露,日志里看到的是合法 JSON,但字段值却是字符串形式的对象——容易被忽略。










