Sooner or later you have to put JSON inside a string: a payload stored in a database column, a field in another JSON document, or a line in a log file. That is when quotes, backslashes and line breaks start breaking things. Here is how JSON string escaping works and how to do it correctly.
What gets escaped
Inside a JSON string, these characters must be written with a backslash:
- a double quote becomes
\" - a backslash becomes
\\ - a new line becomes
\n - a tab becomes
\t - a carriage return becomes
\r - other control characters become
\uXXXX
Writing / as \/ is allowed but not required.
Escape a string in JavaScript
Do not build the escaped text by hand. JSON.stringify does it for you:
const text = 'He said "hi"\nnext line';
const escaped = JSON.stringify(text);
// "He said \"hi\"\nnext line" (with the surrounding quotes)
Unescape a string in JavaScript
JSON.parse reverses it. It expects the surrounding quotes to be there:
const original = JSON.parse(escaped);
// He said "hi"
// next line
JSON inside JSON (double encoding)
This is the case that confuses most people. When a JSON document is stored as a string inside another one, every quote and backslash gets escaped again:
const inner = { name: "Ali", note: 'He said "hi"' };
const outer = { payload: JSON.stringify(inner) };
JSON.stringify(outer);
// {"payload":"{\"name\":\"Ali\",\"note\":\"He said \\\"hi\\\"\"}"}
To read it back you parse twice:
const data = JSON.parse(JSON.parse(outerText).payload);
Python
import json
s = 'He said "hi"\nnext line'
escaped = json.dumps(s)
print(escaped)
# "He said \"hi\"\nnext line"
original = json.loads(escaped)
print(original == s)
# True
One difference to know: json.dumps escapes non-ASCII characters as \uXXXX by default. Pass ensure_ascii=False to keep them readable. JSON.stringify in JavaScript keeps them as they are.
Unicode escapes
JSON can write any character as \uXXXX, and JSON.parse turns it back into the real character:
JSON.parse('"caf\\u00e9"');
// "café"
In Python, json.dumps("café") gives "caf\u00e9", while json.dumps("café", ensure_ascii=False) gives "café".
Common mistakes
-
Using
replaceon quotes only.text.replace('"', '\\"')forgets backslashes and line breaks, and breaks on the first one it meets. -
Parsing text that has no quotes.
JSON.parseon an escaped string needs the surrounding quotes. - Mixing up escape types. JSON escaping is not URL encoding or HTML escaping. Each one has its own rules.
A quick way without code
If you just need to escape or unescape something once, I made a small free tool for it: JSON Escape and Unescape. Paste your text, press Escape or Unescape, and copy the result. It runs in your browser, so what you paste is not uploaded. The site uses Google Analytics for basic page-view counts, but it never sees your text.
If your problem is a broken JSON file rather than a string, the JSON Repair tool and the guide to common JSON parse errors may help.
Top comments (0)