Is there a more efficient way to decoding JSON from QWebSocket?
-
Many (if not most) WebSocket APIs out there use JSON format, which is sent as text frames, which use UTF-8 encoding on the wire. In
QWebSocket
, text frames are handled by following APIs, which expose the message as an already decodedQString
:QWebSocket::sendTextMessage(const QString &message)
QWebSocket::textMessageReceived(const QString &message)
On the other hand, the native JSON support in Qt which is implemented by
QJsonDocument
provide APIs for serializing and deserializing:toJson()
andfromJson()
, which take an UTF-8 encodedQByteArray
.That means, if I want to consume a JSON WebSocket API in Qt, I have to:
- receive a message as
QString
that is already decoded from UTF-8 internally byQWebSocket
- convert it to UTF-8
QByteArray
so I can pass it toQJsonDocument::fromJson()
Analogous but reverse process goes for sending JSON messages.
This seems very inefficient, as there are apparently two needless conversions: UTF-8 -> QString -> UTF-8, before the JSON message can actually by read by
QJsonDocument
.Surely, there must be a more efficient way. Am I missing something? Is there a way to send/receive an UTF-8 encoded string directly using
QWebSocket
? Can these conversions be avoided, or is the Qt API lacking here? Thanks for any clues. -
Hi,
From a very quick look at the class, what about using sendBinaryMessage ?
-
Many (if not most) WebSocket APIs out there use JSON format, which is sent as text frames, which use UTF-8 encoding on the wire. In
QWebSocket
, text frames are handled by following APIs, which expose the message as an already decodedQString
:QWebSocket::sendTextMessage(const QString &message)
QWebSocket::textMessageReceived(const QString &message)
On the other hand, the native JSON support in Qt which is implemented by
QJsonDocument
provide APIs for serializing and deserializing:toJson()
andfromJson()
, which take an UTF-8 encodedQByteArray
.That means, if I want to consume a JSON WebSocket API in Qt, I have to:
- receive a message as
QString
that is already decoded from UTF-8 internally byQWebSocket
- convert it to UTF-8
QByteArray
so I can pass it toQJsonDocument::fromJson()
Analogous but reverse process goes for sending JSON messages.
This seems very inefficient, as there are apparently two needless conversions: UTF-8 -> QString -> UTF-8, before the JSON message can actually by read by
QJsonDocument
.Surely, there must be a more efficient way. Am I missing something? Is there a way to send/receive an UTF-8 encoded string directly using
QWebSocket
? Can these conversions be avoided, or is the Qt API lacking here? Thanks for any clues.@martin_ky said in Is there a more efficient way to decoding JSON from QWebSocket?:
Surely, there must be a more efficient way.
You have a good point: https://bugreports.qt.io/browse/QTBUG-133100
-
Looks like there are QByteArray versions of send and receive for QWebSocket, at least in 6.9
-
Folks suggesting to use
sendBinaryMessage()
andbinaryMessageReceived()
- I don't think that's a choice that I can make as a consumer of a WebSocket API. As far as my understanding of WebSockets protocol go, they work in one of two modes - either transport text frames (encoded as UTF-8 bytes) or binary mode (raw bytes). If the server chooses to send a JSON as a text message, I cannot receive it via thebinaryMessageReceived()
signal -QWebSocket
does not emit this signal when a text message is received. To my knowledge, as of Qt 6.9.1, there is no way to access the UTF-8 bytes of a received text message via theQWebSocket
API, only the already and often unnecessarily decodedQString
.@JKSH: Thanks for the QTBUG - that is exactly my point.
-
Folks suggesting to use
sendBinaryMessage()
andbinaryMessageReceived()
- I don't think that's a choice that I can make as a consumer of a WebSocket API. As far as my understanding of WebSockets protocol go, they work in one of two modes - either transport text frames (encoded as UTF-8 bytes) or binary mode (raw bytes). If the server chooses to send a JSON as a text message, I cannot receive it via thebinaryMessageReceived()
signal -QWebSocket
does not emit this signal when a text message is received. To my knowledge, as of Qt 6.9.1, there is no way to access the UTF-8 bytes of a received text message via theQWebSocket
API, only the already and often unnecessarily decodedQString
.@JKSH: Thanks for the QTBUG - that is exactly my point.
@martin_ky You might like to post something to this effect into the bug report.
-
The only way for the API to know if it is receiving data that is to be binary or text is through the mime-type header. I'd suggest verifying if websocket protocol uses mime-types. If what @martin_ky is true, then he should see appropriate mime-type headers in the transactions.
The other option is to throw out QWebSocket and do TCP level session transport where everything is consider a stream of octets...or of course live with the QString/byte-array translations...I mean, is the amount of data being processed really a bottleneck in translating back and forth?
-
@JonB The bugreport QTBUG-133100 is accurate. I upvoted it. You can too, if you want.
@Kent-Dorfman There is no such thing as mime-type in the WebSocket protocol. Basically, there is just 1 bit in the wire format that differentiates between a text message and a binary messages. When QWebSocket receives a text messages it decodes the UTF-8 payload and emits the QString signal. I see no way around it in Qt 6.9.