为何Node.js通过Socket.io发送JSON需两次JSON.parse才能转对象?
问题原因分析与解决方案
兄弟,我太懂这种困惑了!你这问题核心就是服务器端重复做了JSON序列化,导致发送的内容是「套了一层的JSON字符串」,所以客户端得拆两层才能拿到对象。
为什么会需要两次JSON.parse?
咱们一步步捋清楚:
- 你定义的
dataString本身已经是一个合法的JSON字符串了:'{"test": [ {"M": "A", ...} ]}' - 但你又多做了一步
JSON.stringify(dataString)——这会把这个JSON字符串再一次转成JSON格式的字符串:简单说就是给整个字符串套了双引号,还把里面所有的双引号都转义成了\",最终变成了客户端收到的带转义符的内容:"{\"test\": [ {\"M\": \"A\", ...} ]}\n" - 客户端第一次调用
JSON.parse,其实是把这个带转义的字符串还原成你最初写的dataString(也就是那个原始的JSON字符串);第二次调用才是把这个JSON字符串转成真正的JavaScript对象。
怎么解决?
直接去掉服务器端多余的JSON.stringify就行,给你两种更规范的写法:
方案一:直接发送原始JSON字符串
既然dataString已经是JSON格式的字符串了,直接发出去就行:
const dataString = '{"test": [ {"M": "A", "R": "e", "B": "e", "C": "e", "K": "e", "BD": "e", "CYC": "e"},{"M": "B", "R": "e", "B": "e", "C": "e", "K": "e", "BD": "e", "CYC": "e"}, {"M": "C", "R": "e", "B": "e", "C": "e", "K": "e", "BD": "e", "CYC": "e"},{"M": "D", "R": "e", "B": "e", "C": "e", "K": "e", "BD": "e", "CYC": "e"}]}'; socket.emit('test', dataString);
这种情况下客户端只需要一次JSON.parse就能拿到对象:
socket.on('test', function (message) { const transfer = JSON.parse(message); console.log(transfer.test); // 直接访问对象属性 });
方案二:先转成对象再发送(更推荐)
Socket.io本身会自动帮你序列化/反序列化JSON数据,所以更规范的做法是先把JSON字符串转成JavaScript对象,直接发送对象即可:
// 先把JSON字符串解析成对象 const dataObj = JSON.parse('{"test": [ {"M": "A", "R": "e", "B": "e", "C": "e", "K": "e", "BD": "e", "CYC": "e"},{"M": "B", "R": "e", "B": "e", "C": "e", "K": "e", "BD": "e", "CYC": "e"}, {"M": "C", "R": "e", "B": "e", "C": "e", "K": "e", "BD": "e", "CYC": "e"},{"M": "D", "R": "e", "B": "e", "C": "e", "K": "e", "BD": "e", "CYC": "e"}]}'); // 直接发送对象,Socket.io会自动处理序列化 socket.emit('test', dataObj);
这种情况下客户端连JSON.parse都不用写,收到的message直接就是对象:
socket.on('test', function (message) { console.log(message.test); // 直接用就行! });
内容的提问来源于stack exchange,提问作者user2260979
相关产品推荐
相关产品推荐

