# JSON.isParseableAsJSON()

**URL:** <https://es.discourse.group/t/json-isparseableasjson/2412>\
**Category:** 💡 Ideas\
**Tags:** proposal\
**Created:** [August 11, 2025, 5:39am UTC](https://es.discourse.group/t/json-isparseableasjson/2412 "2025-08-11T05:39:25Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![natewatson999](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/natewatson999/32/2514_2.png) [@natewatson999](https://es.discourse.group/u/natewatson999)\
**Post date:** [August 11, 2025, 5:39am UTC](https://es.discourse.group/t/json-isparseableasjson/2412/1 "2025-08-11T05:39:25Z")

</div>

Right now, if you’re not sure if a particular string is parseable as JSON, most of the solutions basically are all “try to parse the string and have exception handling if it’s not parseable.” This is suboptimal because a string is not guaranteed to be JSON parseable, so it’s a legitimate condition, and one shouldn’t use exception handling for normal non-exception control flow.

Right now, we mostly do things like this:

```javascript
const handleString = function(str) {
  try {
    const parsed = JSON.parse(str);
    //Do whatever with parsed.
  } catch(e) {
    //Do whatever if str is not valid JSON.
  }
};

```

What I’m proposing is introducing JSON.isParseableAsJSON() . It takes a possible parameter and returns a boolean. The resulting value is true if the function has a first parameter defined, said parameter is a string, and said string is valid JSON text. The value is false otherwise.

```javascript
const handleString = function(str) {
  const treatAsObject JSON.isParseableAsJSON(str);
  if (treatAsObject) {
    const parsed = JSON.parse(str);
    //Do whatever with parsed.
    return;
  }
  //Do whatever if str is not valid JSON.
};

```

This allows for normal control flow to be used for normal conditions.

---

<div class="post-metadata">

**Author:** ![aclaymore](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/aclaymore/32/501_2.png) [@aclaymore](https://es.discourse.group/u/aclaymore)\
**Post date:** [August 11, 2025, 6:18am UTC](https://es.discourse.group/t/json-isparseableasjson/2412/2 "2025-08-11T06:18:20Z")

</div>

This would be inefficient. To know if a string is valid JSON it needs to be fully parsed. If it is valid then it is going to do most of that same work again in `JSON.parse`.

[GitHub - Jack-Works/proposal-json-tryParse: JSON.canParse](https://github.com/Jack-Works/proposal-json-tryParse) has been presented in plenary but did not move forward at the time.

There is also

> [@Try Expressions](https://es.discourse.group/t/try-expressions/398):
>
> I think it could be useful if we could try an expression, and if it throws return undefined. Example: let x = (try JSON.parse(y)) ?? {}; equivalent to: let x; try{ x = JSON.parse(y) } catch { x = {}};

> [@Try-catch oneliner](https://es.discourse.group/t/try-catch-oneliner/107):
>
> There is a lot libraries in npm doing similar stuff, if you search [try await](https://www.npmjs.com/search?q=try%20await) you will see a lot libraries which do mostly the same: const [error, result] = tryCatch(JSON.parse, 'hello'); What all this people want is to use more clean syntax for error handling, similar to something [Go already has](https://blog.golang.org/error-handling-and-go). So instead of using such a big construction: let error, data; try { data = JSON.parse('hello'); } catch (e) { error = e; } where you need to use let, 2 code blocks and 3 variables. What I wan…

> [@Enhanced Try Syntax](https://es.discourse.group/t/enhanced-try-syntax/2119):
>
> Proposal: [GitHub - mohsen1/proposal-enhanced-try-syntax: This proposal suggests extending the try statement in JavaScript to allow for more flexible error handling patterns](https://github.com/mohsen1/proposal-enhanced-try-syntax) Hi everyone, I want to introduce a new proposal for making try statements more flexible in JavaScript. The main ideas are: Allow try without catch or finally: try { doSomethingRisky(); } // Code continues here even if there's an error Allow try with just an expression: let data = try JSON.parse(input) ?? {}; These …

> [@JSON.safeParse()：call JSON.parse() in try/catch?](https://es.discourse.group/t/json-safeparse-call-json-parse-in-try-catch/911):
>
> 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](https://www.npmjs.com/package/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…

---

<div class="post-metadata">

**Author:** ![natewatson999](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/natewatson999/32/2514_2.png) [@natewatson999](https://es.discourse.group/u/natewatson999)\
**Post date:** [August 11, 2025, 4:08pm UTC](https://es.discourse.group/t/json-isparseableasjson/2412/3 "2025-08-11T16:08:23Z")

</div>

I acknowledge that it would be inefficient. This just happened to be the only solution I could think of.

I'd also argue that those other proposals are for different problems. Those are more for code simplification, and this one is more for allowing the appropriate code structure in certain cases. Most style guides dislike the use of exception handling for non-exception code branches.

---

<div class="post-metadata">

**Author:** ![aclaymore](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/aclaymore/32/501_2.png) [@aclaymore](https://es.discourse.group/u/aclaymore)\
**Post date:** [August 11, 2025, 4:53pm UTC](https://es.discourse.group/t/json-isparseableasjson/2412/4 "2025-08-11T16:53:52Z")

</div>

> [@natewatson999](#):
>
> Most style guides dislike the use of exception handling for non-exception code branches.

Yes. However those style guides could make an _exception_ for `JSON.parse` as it is built in to the language and is defined to throw for invalid input. So you have no choice but to use `try` to contain the control flow.

---

<div class="post-metadata">

**Author:** ![natewatson999](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/natewatson999/32/2514_2.png) [@natewatson999](https://es.discourse.group/u/natewatson999)\
**Post date:** [August 11, 2025, 6:00pm UTC](https://es.discourse.group/t/json-isparseableasjson/2412/5 "2025-08-11T18:00:06Z")

</div>

I’ve also been told that some people would prefer it be called “JSON.canParse()“.

---

<div class="post-metadata">

**Author:** ![tabatkins](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/tabatkins/32/170_2.png) [@tabatkins](https://es.discourse.group/u/tabatkins)\
**Post date:** [August 11, 2025, 8:43pm UTC](https://es.discourse.group/t/json-isparseableasjson/2412/6 "2025-08-11T20:43:40Z")

</div>

You cannot, in general, tell whether a value can be parsed as JSON without parsing as JSON and seeing if it succeeds. Adding a “can this parse as JSON?” function would just encourage people to parse things twice - once to see if it’s parseable, then again to actually get the value. There’s _almost no reason_ to ever need to know whether something’s parseable without immediately wanting it parsed, so you should just parse it, instead. See, for example, [this blogpost about the Node semver library parsing semvers _twice_ for validation before parsing them for use](https://marvinh.dev/blog/speeding-up-javascript-ecosystem-part-12/).

Having it fail to parse _is_ an exceptional situation; using try/catch for this is perfectly appropriate. You can wrap this in a helper if you want, which can, say, return `undefined` when it fails to parse. Up to you.

---

<div class="post-metadata">

**Author:** ![theScottyJam](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/thescottyjam/32/616_2.png) [@theScottyJam](https://es.discourse.group/u/theScottyJam)\
**Post date:** [August 11, 2025, 9:46pm UTC](https://es.discourse.group/t/json-isparseableasjson/2412/7 "2025-08-11T21:46:29Z")

</div>

> [@natewatson999](#):
>
> This allows for normal control flow to be used for normal conditions.

Note that there's many APIs built into JavaScript and Node that don't follow this idea - it doesn't seem to be something practiced in JavaScript very much.

Another example would be Node’s API to read a file. What if the file does not exist, and you want to handle that the same as, say, the file being empty? I presume you would define that as “normal control flow”, but Node throws an error, expecting you to catch and handle it if you need to do so. You could try checking if the file exists before reading it, but that puts you at risk of race conditions - the file being deleted between the time you read and accessed the file. Really, the only way to design this API after the principle you're describing is to have it return the error instead of throwing it, and that's not very common for JavaScript APIs to do.

There's tons of these sorts of examples. Updating a single function won't really solve the larger problem. I'm not even sure it's worth it to try and solve the larger problem. Some things are so baked into the language that it does more harm than good to try and pivot.

---

<div class="post-metadata">

**Author:** ![jschoi](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/jschoi/32/917_2.png) [@jschoi](https://es.discourse.group/u/jschoi)\
**Post date:** [August 13, 2025, 5:54pm UTC](https://es.discourse.group/t/json-isparseableasjson/2412/8 "2025-08-13T17:54:50Z")

</div>

Adding onto this, here is where [Node’s team discourages checking for a file’s existence before reading it](https://nodejs.org/api/fs.html#fs_fs_access_path_mode_callback):

> Do not use `fs.access()` to check for the accessibility of a file before calling `fs.open()`, `fs.readFile()`, or `fs.writeFile()`. Doing so introduces a race condition, since other processes may change the file's state between the two calls. Instead, user code should open/read/write the file directly and handle the error raised if the file is not accessible.

This is also part of why the Node team deprecated fs.exists.

However, it is also notable that [fs.existsSync was later undeprecated](https://github.com/nodejs/node/commit/7b5ffa46fe4d2868c1662694da06eb55ec744bde).

See also these Node issues:

- nodejs/node#103: [“Deprecate fs.exists or fix its API”](https://github.com/nodejs/node/issues/103)
- nodejs/node#4077: [“fs: un-deprecate existsSync(), throw error on EPERM”](https://github.com/nodejs/node/pull/4077)
- nodejs/node#1592: [“Gripe: deprecating fs.exists/existsSync”](https://github.com/nodejs/node/issues/1592)

There’s maybe an analogy to JSON parsing here. Note that the last linked issue is a very long argument over similar “let me use a boolean predicate” API prescriptivism matters. And the commit that undeprecated existsSync even says:

> As noted in [https://github.com/nodejs/node/pull/7455#issuecomment-228961530](https://github.com/nodejs/node/pull/7455#issuecomment-228961530), while this API is still generally considered an anti-pattern, there are still use-cases it is best suited for, such as checking if a git rebase is in progress by looking if ".git/rebase-apply/rebasing" exists.

I do personally think that, unlike fs.existsSync, a separate JSON.isValid function is probably unnecessary. Even fs.existsSync should generally be avoided except in fairly rare cases.

---

<div class="post-metadata">

**Author:** ![swhiteman](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/swhiteman/32/716_2.png) [@swhiteman](https://es.discourse.group/u/swhiteman)\
**Post date:** [August 15, 2025, 6:00am UTC](https://es.discourse.group/t/json-isparseableasjson/2412/9 "2025-08-15T06:00:11Z")

</div>

`JSON.canParse()` would also have side effects (or rather _lack_ of desired side effects) in the web platform, as `Request#json()` and `Response#json()` [explicitly call JSON.parse()](https://infra.spec.whatwg.org/#parse-a-json-string-to-an-infra-value).

(Also a naive implementation of `Request#canJSON()` would be impossible because the body would be marked consumed just by test-parsing. There would have to be an implicit `tee` to consume it again. Obviously this isn’t ES business but for context.)

---

<div class="post-metadata">

**Author:** ![6562680](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/6562680/32/2280_2.png) [@6562680](https://es.discourse.group/u/6562680)\
**Post date:** [August 17, 2025, 11:06pm UTC](https://es.discourse.group/t/json-isparseableasjson/2412/10 "2025-08-17T23:06:25Z")

</div>

Same in PHP - it returns NULL if incoming is NULL and also if parsing is failed  
I’ve solved it writing wrapper function with first parameter: fallback

if fallback is NULL - function returns Result\<T,E\> object  
if fallback is empty array - function throws exception  
if fallback has non-empty array - function returns ZERO key of the array - so any data can be returned AS-IS without conversion

Then it looks like

`myJson.parse([], anyVariable); // may throw exception`  
`myJson.parse([NAN], anyVariable); // returned NAN if error`  
`myJson.parse([NULL], anyVariable); // returned NULL if error`  
`myJson.parse([this], anyVariable); // returned this if error (awesome check that - if (this === result) - ideal error match, because this can be only inside current scope. Otherwise it is “other this”.`  
`myJson.parse(null, anyVariable).get{Value|Errors}();`
