# JSON.isWellFormed(str: string): boolean

**URL:** <https://es.discourse.group/t/json-iswellformed-str-string-boolean/2438>\
**Category:** 💡 Ideas\
**Created:** [September 29, 2025, 8:18am UTC](https://es.discourse.group/t/json-iswellformed-str-string-boolean/2438 "2025-09-29T08:18:37Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![cesco69](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/cesco69/32/1481_2.png) [@cesco69](https://es.discourse.group/u/cesco69)\
**Post date:** [September 29, 2025, 8:18am UTC](https://es.discourse.group/t/json-iswellformed-str-string-boolean/2438/1 "2025-09-29T08:18:37Z")

</div>

### Introduction

This proposal introduces a new method to the `JSON` namespace:

```javascript
JSON.isWellFormed(str: string): boolean

```

The method returns `true` if and only if the input string does **not** contain characters that would require escaping when serialized via `JSON.stringify`.

### Motivation

In many applications, developers want to know in advance whether a string will produce a "clean" JSON representation, without escape sequences.

Examples:

- Optimizing serialization performance.
- Ensuring human-readable JSON outputs.
- Validating user input before sending data over the network or storing in a database.

A dedicated `JSON.isWellFormed` method would provide a fast, standardized way to check this.

### Definition

A string is considered **well-formed for JSON** if it does **not** contain:

1. ASCII control characters: `U+0000` → `U+001F`
2. Quotation mark (`"`, `U+0022`)
3. Reverse solidus (backslash, `\`, `U+005C`)
4. Unpaired UTF-16 surrogates: `U+D800` → `U+DFFF`

### Examples

```javascript
JSON.isWellFormed("hello world");
// → true

JSON.isWellFormed("hello \"world\"");
// → false (contains quotation mark)

JSON.isWellFormed("line \n break");
// → false (contains control char)

JSON.isWellFormed("emoji 😀");
// → true

JSON.isWellFormed("\uD800"); 
// → false (lone surrogate)

```

### Possible Specification (Informal)

```javascript
function isWellFormed(str) {
  for (let i = 0; i < str.length; i++) {
    const code = str.codePointAt(i);

    // ASCII control characters
    if (code <= 0x1F) return false;

    // " or \
    if (code === 0x22 || code === 0x5C) return false;

    // Unpaired surrogate
    if (code >= 0xD800 && code <= 0xDFFF) return false;

    if (code > 0xFFFF) i++; // skip surrogate pair
  }
  return true;
}

```

### Prior Art

- **`String.prototype.isWellFormed`** and **`String.prototype.toWellFormed`** (added in ES2024) ensure valid Unicode strings but are unrelated to JSON escaping.
- This proposal specifically targets **JSON serialization safety**.

---

<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:** [September 29, 2025, 8:33am UTC](https://es.discourse.group/t/json-iswellformed-str-string-boolean/2438/2 "2025-09-29T08:33:25Z")

</div>

> [@cesco69](#):
>
> In many applications, developers want to know in advance whether a string will produce a "clean" JSON representation, without escape sequences.

would you be able to share links to code that is checking this?

In my experience most code is using JSON as a serialisation format, so they only care that you’ll get the same value back when parsing the JSON. Not if it needs to include escape characters to do so.

---

<div class="post-metadata">

**Author:** ![cesco69](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/cesco69/32/1481_2.png) [@cesco69](https://es.discourse.group/u/cesco69)\
**Post date:** [September 29, 2025, 8:38am UTC](https://es.discourse.group/t/json-iswellformed-str-string-boolean/2438/3 "2025-09-29T08:38:33Z")

</div>

see [fast-json-stringify/lib/serializer.js at cc14cc8abe958274cacca05e8ab8e3a8fd0410b8 · fastify/fast-json-stringify · GitHub](https://github.com/fastify/fast-json-stringify/blob/cc14cc8abe958274cacca05e8ab8e3a8fd0410b8/lib/serializer.js#L116)

"fastify" check those chars for each response because it use a built in json-stringify ([GitHub - fastify/fast-json-stringify: 2x faster than JSON.stringify()](https://github.com/fastify/fast-json-stringify))

---

<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:** [September 29, 2025, 8:53am UTC](https://es.discourse.group/t/json-iswellformed-str-string-boolean/2438/4 "2025-09-29T08:53:47Z")

</div>

Thanks! So it’s common for custom JSON encoder libraries, rather than the top level application itself?

---

<div class="post-metadata">

**Author:** ![cesco69](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/cesco69/32/1481_2.png) [@cesco69](https://es.discourse.group/u/cesco69)\
**Post date:** [September 29, 2025, 9:01am UTC](https://es.discourse.group/t/json-iswellformed-str-string-boolean/2438/5 "2025-09-29T09:01:52Z")

</div>

It’s not very common in everyday usage, but it can be extremely useful in critical high-traffic scenarios. `JSON.stringify` is relatively slower, and custom stringifiers can provide a real performance boost.

see:

- [https://www.npmjs.com/package/fast-json-stringify](https://www.npmjs.com/package/fast-json-stringify)
- [https://www.npmjs.com/package/json-accelerator](https://www.npmjs.com/package/json-accelerator)

custom stringifiers need something like `JSON.isWellFormed()`

Actually it uses regex

> <https://github.com/elysiajs/json-accelerator/blob/7fcbf62c8a627cb87c89cf660438808a8128f837/src/index.ts#L176>

> <https://github.com/fastify/fast-json-stringify/blob/cc14cc8abe958274cacca05e8ab8e3a8fd0410b8/lib/serializer.js#L4>

but regex are slow!

---

<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:** [September 29, 2025, 6:49pm UTC](https://es.discourse.group/t/json-iswellformed-str-string-boolean/2438/6 "2025-09-29T18:49:27Z")

</div>

I think you’re reversing cause and effect here. The restrictive JSON stringifiers are faster **because** they model output on a schema (either official JSON Schema(tm) or something proprietary) and do not support the entire JSON grammar.

"Well-formed" is thus a misnomer and even the authors of those packages wouldn’t call their happy path "well-formed," it’s just simple enough for them to use all-userland code.

Like you wouldn’t call a CSV "well-formed" if it doesn’t have escaped delimiters and dquotes, would you? You might call it "simple" or "naive" though.

---

<div class="post-metadata">

**Author:** ![michael](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/michael/32/11_2.png) [@michael](https://es.discourse.group/u/michael)\
**Post date:** [September 30, 2025, 3:29pm UTC](https://es.discourse.group/t/json-iswellformed-str-string-boolean/2438/7 "2025-09-30T15:29:09Z")

</div>

> [@cesco69](#):
>
> but regex are slow

What makes you think that your proposed method would be any faster? And why do you think regexps are slow?

---

<div class="post-metadata">

**Author:** ![cesco69](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/cesco69/32/1481_2.png) [@cesco69](https://es.discourse.group/u/cesco69)\
**Post date:** [October 1, 2025, 7:01am UTC](https://es.discourse.group/t/json-iswellformed-str-string-boolean/2438/8 "2025-10-01T07:01:04Z")

</div>

About performance, similar to `String.prototype.isWellFormed()` ([docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/isWellFormed#description)):

> `isWellFormed()` is more efficient, as engines can directly access the internal representation of strings.

In the same way, JSON.isWellFormed could access the internal representation of strings and thus be more efficient than using regular expressions.

eg. in V8 [src/json/json-stringifier.cc - v8/v8 - Git at Google](https://chromium.googlesource.com/v8/v8/+/refs/heads/main/src/json/json-stringifier.cc#543) the efficiency comes from vectorized word-level scanning, with a fallback to per-character checks when needed. This is what should be exposed as `JSON.isWellFormed`
