为什么Sock.js使用双json编码

Why Sock.js use double json encoding?

本文关键字:json 编码 Sock js 为什么      更新时间:2023-09-26
 var sock = new SockJS(url, {'protocols_whitelist': ['xhr-polling']});
 sock.onopen = function() {
     var msg = {msg: "hello"};
     sock.send(msg); // 1. example
     sock.send(JSON.stringify(msg)); // 2.example
 };

1。示例google chrome payload

["[object Object]"]

2。示例google chrome payload

["{'"msg'":'"hello'"}"]

我发现在sock.js中显式转换为字符串发生在这里(第253行):

https://github.com/sockjs/sockjs-client/blob/master/lib/sockjs.js L253

这就是为什么我看到["[object Object]"]时js对象直接发送(因为'' + data转换data为字符串)。

 that._transport.doSend(utils.quote('' + data));

SockJS.prototype.send = function(data) {
    var that = this;
    if (that.readyState === SockJS.CONNECTING)
        throw new Error('INVALID_STATE_ERR');
    if (that.readyState === SockJS.OPEN) {
        that._transport.doSend(utils.quote('' + data)); // here
    }
    return true;
};

但这仍然有效。报价是

https://github.com/sockjs/sockjs-client/blob/master/lib/utils.js L292

// Quote string, also taking care of unicode characters that browsers
// often break. Especially, take care of unicode surrogates:
//    http://en.wikipedia.org/wiki/Mapping_of_Unicode_characters#Surrogates
    utils.quote = function(string) {
        var quoted = quoteJSON(string);
        // In most cases this should be very fast and good enough.
        extra_escapable.lastIndex = 0;
        if(!extra_escapable.test(quoted)) {
            return quoted;
        }
        if(!extra_lookup) extra_lookup = unroll_lookup(extra_escapable);
        return quoted.replace(extra_escapable, function(a) {
            return extra_lookup[a];
        });
    }; 

最后:

https://github.com/sockjs/sockjs-client/blob/master/lib/utils.js L261

var quoteJSON = (JSON3 && JSON3.stringify) || function(string) {
    json_escapable.lastIndex = 0;
    if (json_escapable.test(string)) {
        string = string.replace(json_escapable, function(a) {
            return json_lookup[a];
        });
    }
    return '"' + string + '"';
};

正如你所看到的,当你想要发送JSON时,你需要显式调用JSON。你自己将字符串化,然后Sock.js将同样的事情再次发生在你传递给sockjs_instance.send的字符串上。

为什么需要编码两次?问题是我需要在服务器上做一些hack来解码消息,因为默认情况下,单个JSON.decode不像sock.js那样将所有作为字符串数组发送。这是性能问题。

正如你所看到的,当你想要发送JSON时,你需要显式调用JSON。你自己将字符串化,然后Sock.js将同样的事情再次发生在你传递给sockjs_instance.send的字符串上。

Websockets API假定传递给"send"的数据是文本。(或二进制,SockJS不支持)。这就是为什么"send"调用希望它是文本。

SockJS有时确实需要对它进行编码,我们只是碰巧使用了json。JSON很快(因为它通常是内置的)。实际上,我们使用您在代码中发现的修改过的JSON编码来避免unicode问题。

是的,理论上对于某些传输来说,在传递丰富数据时可以避免双重编码,但是这样做不值得破坏与本机WS的兼容性。