Search code examples
javascriptjsonnode.jsv8

Strange JSON.parse() error in node.js


I'm retrieving some stringifyed JSON via TCP in node.js an want to parse it. So my approach is similiar to this. I shortend and simplified it, so you don't have to know the surrounding logic.

socket.on("data", function(data) {
    console.log(data.toString());               // Shows the original stringifyed version
    console.log(JSON.parse(data.toString()));   // Doesn't work
});

The complete (beautified) JSON is this. As you can see, there are no errors.

{
    "result": "success",
    "source": "chat",
    "success": {
        "message": "test",
        "time": 1331770513,
        "player": "silvinci"
    }
}

But JSON.parse(data.toString()) always throws me this dumb error:

{"result":"success","source":"console","success":{"time":1331762264,"line":"20
^
SyntaxError: Unexpected token {
    at Object.parse (native)
    at Socket.<anonymous> (/home/node/api.js:152:35)    // irrelevant from here on
    at Socket.emit (events.js:67:17)
    at TCP.onread (net.js:347:14)

So I thougt: "What could be wrong with the JSON-String. Let's try it directly. Should not work." Surprise, Surprise! It worked. Why does it work when I directly enter the String?


Solution

  • Thanks to @Felix Kling I found my bug. It's very important to filter unescaped characters, especially outside the stringified JSON. I didn't and overlooked an invisible linebreak right after the stringified JSON.

    This is the fix:

    socket.on("data", function(data) {
        console.log(data.toString());                          // Shows the original stringified version
        console.log(JSON.parse(data.toString().slice(0, -4))); // Trim the sequence "\r\n" off the end of the string
    });
    

    Please note, that this only works for me, as I have a very specialized case. The server is always responding in lines of JSON, that are terminated with an \r\n - not the whitespace characters, but literally backslash r and backslash n.
    Your code may (or probably) fail due to other errors. But checking the server's response is a good starting point when you get parsing errors.

    As @Zack correctly pointed out, this is a more general fix for removing unintended whitespace:

    JSON.parse(data.toString().trim());