Solution to SignalR error 'Unexpected token in JSON' when parsing event data
source link: https://blog.jongallant.com/2021/09/signalr-unexpected-token-in-json/?utm_campaign=Feed%3A+jongallant+%28Jon+Gallant%29
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Solution to SignalR error 'Unexpected token in JSON' when parsing event data
I’ve been writing some UI automation tests with Playwright and was trying to parse a SignalR event. Like so:
const imageEvent = JSON.parse(event.payload.toString()) as ImageEvent;
And I got this error:
1) tests/memealyzer.spec.ts:15:1 › Add Meme Test =================================================
webSocket.waitForEvent: Unexpected token in JSON at position 658
49 | expect(afterCardCount).toEqual(beforeCardCount + 1);
50 |
> 51 | await webSocket.waitForEvent("framereceived", (event) => {
| ^
52 | if (event.payload.indexOf("ReceiveImage") > 0) {
53 | const imageEvent = JSON.parse(event.payload.toString()) as ImageEvent;
As you can see from this screenshot:
Screenshot
It looks like a christmas tree is in my JSON. I assumed it was an invalid char added by my code or playwright’s code, etc.
Here’s what it looks like in the debugger:
Debugger
So, I removed it like so:
const payload = event.payload.toString().replace("", ""); // Remove hidden char
Replace
Little did I know that character is a record separator! After I tweeted my code, David Fowler pointed me to this:
You want to split based on that character instead of removing it. A single websocket payload can contain multiple messages https://t.co/3sHUdjCpoB
— David Fowler 🇧🇧💉💉 (@davidfowl) September 1, 2021
Here’s the code that SignalR uses to parse and iterate through the results:
https://github.com/dotnet/aspnetcore/blob/e18394c8a933a5e03c0f5e4d614b622c2cb0a4b7/src/SignalR/clients/ts/signalr/src/TextMessageFormat.ts#L6-L22
So, instead of removing the char, I now split on it and loop through the results.
await webSocket.waitForEvent("framereceived", (event) => {
if (event.payload.indexOf("ReceiveImage") > 0) {
const imageEvents = TextMessageFormat.parse(event.payload.toString());
for (let imageEventRaw of imageEvents) {
const imageEvent = JSON.parse(imageEventRaw) as ImageEvent;
actualId = imageEvent.arguments[0].Id;
return true;
}
}
});
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK