Just File Tools

String to JSON

Unescape stringified JSON — paste once, get a real object back

Unescaped 2 levelsResult: object (3 top-level keys)

How to String to JSON Online

Convert stringified JSON (with escaped quotes and backslashes) into a real, readable JSON document.

  1. Paste your stringified JSON into the input field. Common sources: a JSON column in a log, an error message body, a `JSON.stringify`'d value inside another JSON object, or a string copied out of a JavaScript source literal.
  2. The tool detects how many levels of stringification it has to unwrap and shows the count (e.g., 'Unescaped 2 levels'). You don't have to know in advance — it tries until it lands on a real object, array, or primitive.
  3. Review the parsed result. If it's an object or array, it gets pretty-printed with your chosen indent (2 or 4 spaces). If it's a primitive (string, number, boolean), the raw value is shown.
  4. Copy the result with the Copy button, or hand it off to the JSON Formatter for further work.

About String to JSON

Stringified JSON is the most boring bug in software. Nothing is technically wrong — every value passes JSON.parse without complaint, every API returns a valid response — but the data your code expects to be an object is instead a string that contains an object. You parse it, you get back a string. You print it, you see escaped quotes everywhere. Nothing works, and the error messages don't tell you why because nothing failed.

This happens for predictable reasons. Logging libraries serialize objects to strings before writing to disk. Message queues serialize payloads when they go onto the wire. Database columns of type `text` or `varchar` store JSON as a serialized string. PostgreSQL has `jsonb` for structured storage but most schemas predate it and use plain text columns. Every time data crosses one of these boundaries, it gets wrapped in another layer of stringification. Two crossings and you have JSON-in-JSON.

The fix is straightforward: `JSON.parse` the string to get the inner JSON, then format it. The annoying part is that you usually have to do it in a browser dev tools console or write a one-off script, and if the data is escaped multiple times you have to run `JSON.parse` multiple times. This tool does exactly that, automatically, with a counter so you can see how many layers came off.

The interface is intentionally minimal:

- One input box for the stringified JSON. - A counter showing how many levels of nesting were peeled. - A pretty-printed output box, ready to copy. - A toggle for 2-space vs 4-space indent.

The algorithm is simple: keep calling `JSON.parse` while the result is still a string, up to a cap of 10 levels (which handles every realistic real-world case while preventing pathological inputs from looping forever). If the input was already a parseable JSON object or array, the tool reports level 1 and just formats it. If it was stringified once, level 2. If twice, level 3. Most users see level 2 — that's the "I copied JSON out of a log message" case.

There's a fallback path for a slightly different scenario. Sometimes you copy a JSON value out of a source code literal and you get the inside of the literal without the outer quotes — text like `{\"foo\":\"bar\"}` with escape sequences but no enclosing `"` characters. To a plain parser, this is invalid syntax. This tool detects the escape sequences (the `\"` and `\n` and `\u00e9` patterns) and tries to re-add the outer quotes before parsing. It works for almost every case. The exception is text with *unescaped* `"` characters mixed in — that's a broken source string, not a parseable one, and no tool can recover it without guessing.

A few practical tips.

**Spot multi-level nesting in production.** If this tool reports level 3 or higher on a real payload, something in your pipeline is double-encoding. That's usually a bug worth fixing at the source: a logger serializing an already-serialized value, a queue producer encoding twice, a database column being written with `JSON.stringify(JSON.stringify(...))`. The level counter is a quick diagnostic.

**The output of this tool is regular JSON.** You can paste it into the JSON Formatter for syntax-highlighted viewing, into the JSON Diff to compare against another version, or into any code editor with JSON support. The escape sequences are gone.

**Strings inside the result are fully decoded.** A value like `"line one\nline two"` becomes the two-line string you'd expect, with the literal newline character — not the escape sequence. If you need to re-escape it later (to put it back into another JSON context), use `JSON.stringify` in the dev tools console or write the value back through this tool's input and observe how it gets re-encoded.

**Privacy.** This whole operation is native `JSON.parse` running inside your browser. Nothing crosses the network. You can verify in DevTools — paste anything, copy the result, and watch the network panel stay empty. Sensitive log entries, internal API responses, anything you shouldn't be sending to a third-party tool — all stays in your tab. That's the entire point of how this site works.

**Edge cases handled correctly:** BOM-prefixed input (the leading U+FEFF gets trimmed before parsing); whitespace-only input (reported as empty, not parsed as null); JSON primitives at the top level (numbers, booleans, null all unwrap correctly); deeply nested objects (no recursion-depth limit — the result is a JavaScript value that JS itself can hold).

**One thing it doesn't do:** repair broken JSON. If your input has a trailing comma, an unquoted key, a single-quoted string, or some other non-spec syntax, `JSON.parse` will reject it and you'll see the parser's error message. For loose-JSON repair, you need a different tool (json5, hjson). This one is strict on purpose — if your data has parser errors, knowing about them is more useful than silently coercing.

The companion to this tool is the JSON Formatter, which now also auto-detects stringified input on paste. Either tool works for the same use case. Use this one if you want a focused unescape-only workflow; use the Formatter if you want format+minify+validate in addition.

Frequently Asked Questions

Why do I need to unescape JSON in the first place?

Because logs, error messages, database columns, and API responses often store JSON values as **strings instead of objects**. When you copy that string out of its container, you get the escaped form — every `"` inside the JSON has been replaced with `\"`, every newline with `\n`, every backslash with `\\`. The result is technically valid JSON (it's a string), but its contents are a different document hiding inside. To read or work with that inner document, you have to unescape it back. This tool does that automatically and handles multi-level nesting (JSON inside JSON inside JSON, as deep as 10 levels).

Why did the standard JSON Formatter fail when I pasted my data?

Because to a plain JSON parser, a stringified value like `"{\"foo\":\"bar\"}"` is just a string with 17 characters in it. It parses without error and gives you back a string. The Formatter then formats that string as a JSON string literal — which is exactly what you don't want. You wanted the **inner** JSON. This tool detects the situation and unwraps repeatedly until it reaches a real object, array, or primitive. (The JSON Formatter on this site has been updated to auto-detect this case too — paste once, get the right thing either way.)

What does the 'level' count mean?

How many times JSON.parse had to run to reach the final value. Level 1 means it was already valid JSON (no unescaping needed). Level 2 means it was stringified once (the typical case of a JSON value stored inside another JSON value). Level 3+ means somebody stringified JSON, then stored *that* string in JSON, then stringified again. Multi-level escaping happens more than you'd think — log pipelines, message queues, and serialization libraries can each add a layer without anyone noticing until it's time to read the data.

What if I paste a string that has escape sequences but no outer quotes?

That's the case where you copied the content of a JavaScript string literal out of source code — the source code looks like `const data = "{\"foo\":\"bar\"}"` and you grabbed everything inside the outer quotes, getting `{\"foo\":\"bar\"}`. This tool detects the escape sequences and tries to re-add the outer quotes before parsing. Works for most cases. If your text has *unescaped* `"` characters mixed in, the fallback can't recover — you'll need to fix the source data.

Does it handle non-object JSON values?

Yes. The final unwrapped value can be an object, an array, a string, a number, a boolean, or null. If the result is a string that doesn't itself look like JSON, the tool stops there and shows you the cleaned-up string. If you wanted that string to be parsed further, you can copy it back into the input and run again.

Why is there a max-level limit of 10?

Defense against pathological input. Without a limit, a malicious or accidentally-recursive string could cause the loop to run forever. Real-world data essentially never goes past 3 levels of nesting; 10 is a safe ceiling that handles every realistic case while protecting the browser tab from a stuck loop.

Is this different from `JSON.parse` twice?

Functionally, no — that's what the tool is doing internally. The value is calling `JSON.parse` in a loop until the result is no longer a string. The UI just gives you a clean place to paste and copy without writing code, and the level counter shows you how many layers were peeled off so you can spot when your data pipeline is double-encoding things.

Is the JSON sent to a server?

No. Parsing happens entirely in your browser using the native `JSON.parse` function. There are no network requests during operation. Verify in DevTools — paste, copy, and you'll see zero outgoing traffic. This is the same as every other tool on this site.