Handling bad JSON.parse() in node safely

61,824

Solution 1

The best way to catch invalid JSON parsing errors is to put the calls to JSON.parse() to a try/catch block.

You really do not have any other option - the built-in implementation throws an exception on invalid JSON data and the only way to prevent that exception from halting your application is to catch it. Even using a 3rd party library will not avoid that - they must do a try/catch on a JSON.parse() call somewhere.

The only alternative is to implement your own JSON parsing algorithm that could be more forgiving on invalid data structures, but that feels like digging a 1 cubic metre hole with a small nuke.

Note about performance

The v8 JavaScript engine used by Node.js cannot optimise functions which contain a try/catch block.

Update: v8 4.5 and above can optimise try/catch. For older releases, see below.

A simple workaround is to put the safe-parsing logic into a separate function so that the main function can still be optimised:

function safelyParseJSON (json) {
  // This function cannot be optimised, it's best to
  // keep it small!
  var parsed

  try {
    parsed = JSON.parse(json)
  } catch (e) {
    // Oh well, but whatever...
  }

  return parsed // Could be undefined!
}

function doAlotOfStuff () {
  // ... stuff stuff stuff
  var json = safelyParseJSON(data)
  // Tadaa, I just got rid of an optimisation killer!
}

If the JSON parsing is done sporadically, this might not have a noticeable effect on performance, but if used improperly in usage-heavy function it could lead to dramatic increase in response times.

Note about try/catch being blocking

It should be noted that every.single.statement of JavaScript code in Node.js is executed only one-at-a-time, no matter if it's called from the main function or from a callback or from a different module or whatever. As such, every single statement will block the process. This is not necessarily a bad thing - a well designed application will spend most of its time waiting for an external resource (database response, HTTP communication, filesystem operations etc.). It is therefore of great importance that frequently executed JavaScript code can be optimised by the v8 engine so it takes as little time as possible in this blocked state - see the note about performance.

Solution 2

You can use try and catch

function parseMyHeader(){
    try {
      return JSON.parse(req.headers.myHeader);
    } catch(ex){
      return null;
    }
}

Solution 3

The standard try/catch is the correct way to handle a JSON.parse error in node.js, as mentioned in the node production practices for error handling docs from the joyent website, which says:

...the only commonly-used case where you'd use try/catch is JSON.parse and other user-input validation functions.

Which is also in agreement with the link to nodejitsu which Aleksandr supplied in his comment.

Solution 4

        var parsed;

        try {
            parsed = JSON.parse(data);
        } catch (e) {
            parsed = JSON.parse(JSON.stringify(data));
        }

        root = parsed;

Well this worked for me. In Catch I converted the data to stringify before parsing it to JSON.

Share:
61,824
tpie
Author by

tpie

Updated on March 23, 2021

Comments

  • tpie
    tpie about 3 years

    Using node/express - I want to get some JSON out of request headers, but I want to do it safely.
    If for some reason it's not valid JSON, it's fine, it can just return false or whatever and it will just reject the request and keep going. The problem is it throws a syntax error if it's not valid JSON. Normally I want a syntax error to blow up, but not in this case.

    var boom = JSON.parse(req.headers.myHeader);

    Do I scrape the stack and check for a bad parse call from that particular module, and if it's the case, it ignores it? That seems a bit crazy. Surely there's a better way.

    EDIT: I am aware that try/catch blocks are A way of handling this error, but is it the best way in a node app? Will this way block node?

  • Eric
    Eric about 9 years
    You can also return null (which evaluates to false), for the sake of parsing
  • EJTH
    EJTH almost 9 years
    You are completely right. Of course you should return null!
  • Tom Spencer
    Tom Spencer about 8 years
    Thank you for this very concise and well-written answer, particularly the point about optimisation.
  • Franck Freiburger
    Franck Freiburger about 6 years
    since JSON.parse() will never return undefined, maybe returning undefined on parsing error may help to identify parsing errors
  • Julfikar
    Julfikar over 4 years
    Why "1" is json parsable?
  • csvan
    csvan over 3 years
    For completeness, it should be noted that V8 now optimizes try-catch since the introduction of the TurboFan compiler. news.ycombinator.com/item?id=12178856