JSON.safeParse():call JSON.parse() in try/catch?

It it a very common practice to put JSON.parse() in try/cath to prevent throwing exceptions:

function safeParse(str) {
  let parsed;

  try {
    parsed = JSON.parse(str);
  } catch (error) {
    console.error(error);
  }

  return parsed;
}

A lot of community solutions solved this problem in similar way. The weekly download of safe-json-parse is above 600, 000, which is quite impressive. It also shows the importance of this problem.

It is said that try/catch may affect the perfomance, but v4.5 of V8 has already solved this problem. I will provide more benchmark result about this. And since a lot of people call JSON.parse() in try/catch anyway, performance is not a practical problem.

Why not add JSON.safeParse() to ECMAScript?

Reference

Well the goal is not to "prevent exceptions", it is to handle errors from invalid input. For which try/catch is the normal and idiomatic solution, and the code in the catch block is application-specific.

No, it shows that safe-json-parse is used as a dependency of two other popular packages (video.js and body). It does not show that people perceive this as a problem or that they prefer this style (actually, any of the three styles offered by that package) over the normal try/catch.

1 Like

I think the safeParse method is nessary, it reminds developer that JSON.parse is not safety, when you use it, you should be careful. by the way, json is the most important data structure in js you know, safeParse will improve the robustness of the program, and less try/catch block.

That sounds like an argument for providing a better name for JSON.parse(), not for changing its behavior. e.g. would you be happy if we provided a JSON.attemptParse() or JSON.dangerouseParse() that functioned exactly the same as JSON.parse(), but its naming reminds you that you should catch and handle any errors (or don't catch them if you're certain an error should not be thrown)?

(edit: Not that I would encorage that we do this kind of renaming - I was just trying to figure out this point of view)

JSON.parse is not unsafe. It can throw exceptions, like any other function that has some requirement on its input. Which in this case, is that the input must be well-formed JSON. I think that's obvious from the name "parse".

Second, I don't see how swallowing exceptions improves the robustness of a program.

If your main concern is that try/catch blocks are too verbose, then adding a single function wrapper doesn't solve anything. You want more concise, generic syntax.

2 Likes

Yes - I would add that its equally likely for someone to forget to handle the error from JSON.parse(), as it is for someone to forget to handle the fact that JSON.safeParse() may return undefined if you received invalid JSON. In the first case, you'll get a nice error explaining exactly what went wrong. In the second case, you'll probably end up with a less useful error like "Cannot read property 'someExpectedJSONProperty' of undefined"

2 Likes

I feel like having this built-in will be useful. To @theScottyJam 's point, I agree it is equally as likely, but my fear with relying on the generic try/catch is that something else may fail in the block (like a mistyped variable reference). A developer may in that case think they've received an invalid JSON because there isn't a way to identify the nature of the error (with the generic try/catch) approach. Technically a developer can test against a SyntaxError, but this pattern is really unusual and not used widely enough in examples in the web.

The built-in will be a way for the platform to provide a standard way of handling the parse error without potentially conflating it with other errors.

Technically a developer can test against a SyntaxError, but this pattern is really unusual and not used widely enough in examples in the web.

It's really bad whenever people just catch and swallow any error in a try block, when they could have looked for a more specific exception instead. I cry a little inside whenever I see that :(.

There is this draft proposal for adding special syntax to make it easier to catch specific errors using pattern-matching syntax. I'm hoping for something like this to go in, and hopefully once that's in, people will do a little better at catching specific errors instead of all errors.

I was planning to suggest the same thing here. I both agree that JSON.parse is not very open when it says that it should be handled in a try/catch block, and I also agree that this is the most idiomatic solution.

However, when we are dealing not with the parsing itself but with the validation of data, sometimes this gets very cumbersome to deal with, because you have to do everything inside a catch block which essentially breaks down your code into two different scopes.

My opinion is that JSON.parse could continue to exist, but following Zod | Documentation we could include a safeParse method that does the same, but my implementation would be a bit different:

function safeParse (str) {
  try {
    return { success: true, value: JSON.parse(str) }
  } catch (e) {
    return { success: false, error: e }
  }
}

I had to do this multiple times already and I'm pretty convinced this would help a lot by being in the spec

This is on the agenda for the next meeting for stage 1, so still early but related.

Problem to solve

try { return JSON.parse(str) } catch { return undefined }

1 Like