What this tool does
JSON escape is the small transformation between a piece of text and a valid JSON string value: the
quotes, the backslashes and the control characters get a \ in front of them, and everything else
stays as it is. This page does it in both directions, and it does the reverse carefully — telling
you exactly which sequence is invalid and where it starts, rather than failing with a position in a
document you never wrote.
There is a third mode for the case that comes up more often than it should: taking an entire JSON
document and turning it into a single string value, ready to be the payload field of another one.
How to use it
- Choose the direction: escape, unescape, or embed a whole document.
- Turn on quotes if you want a value you can paste straight into a file.
- Paste, then copy the result.
The rules, in full
JSON string escaping is one of the smallest specifications in wide use. Two characters must be
escaped because they would otherwise end the string or start an escape: the double quote and the
backslash. Every character below U+0020 must be escaped because the grammar forbids a raw control
character inside a string — five of them have short names (\b, \f, \n, \r, \t) and the
rest use \u followed by four hexadecimal digits. The forward slash may be escaped and never has
to be. Nothing else is special.
That list is short enough to implement by hand, which is exactly the trap. Use JSON.stringify in
any language that has it. It is the reference implementation of these rules, it handles the
surrogate pairs, and it will not forget the vertical tab at two in the morning.
Where the double encoding comes from
The commonest reason people arrive at a page like this is a string that has been escaped twice: a
value that should read C:\temp shows up as C:\\\\temp, or a newline appears as the four
characters \ \ n — and no amount of staring makes it parse.
It is always the same shape. A service serialises a structure to JSON and logs the resulting text. A collector treats that log line as a plain string field and serialises again. Each pass escapes the escapes of the previous one, so backslashes double every time. Unescaping once per layer gets you back; the escape counter here goes to zero when there is nothing left to peel.
The cure is upstream: log the object and let the logger serialise once, or store the document as a nested object instead of a string. When it genuinely has to be a string — a queue message that carries an opaque payload — use the embed mode here, and reach for the JSON formatter first to confirm the document parses before you wrap it.
The forward slash and old JavaScript
\/ is the strangest thing in the specification: an escape that is allowed, changes nothing, and
exists for a reason outside JSON. If a document is written into an HTML <script> block, the HTML
parser looks for the closing tag before the JavaScript parser sees anything, so a string containing
that sequence ends the script early. Escaping the slash splits it up while leaving the value
identical.
Modern applications serve JSON from an endpoint rather than inlining it, and the problem disappears with the practice. Keep the option for the templates that still do it, and remember that a value also has to survive the HTML around it — the HTML entity encoder is the tool for that half.