Escapar uma string JSON significa transformar um texto qualquer em uma string que pode ficar com segurança dentro de um documento JSON como literal de string. Um punhado de caracteres — as aspas duplas, a contrabarra e caracteres de controle como quebra de linha e tabulação — carregam significado estrutural ou simplesmente são ilegais dentro de uma string JSON, então cada um deles é substituído por uma sequência de escape segura como \", \\ ou \n. Faça isso errado e seu payload deixa de ser analisado.
Você cai nisso o tempo todo: ao aninhar um objeto JSON dentro de outro como campo de string, ao colar um trecho de código de várias linhas em um valor de configuração ou ao montar à mão o corpo de uma requisição REST para o curl. Este guia mostra exatamente quais caracteres precisam de escape, esclarece a confusão entre escapar e JSON.stringify, percorre o aninhamento JSON-em-JSON e os escapes Unicode, e lista as armadilhas que quebram payloads de forma silenciosa. Se você só quer escapar algo agora mesmo, nossa ferramenta Escape JSON faz isso no navegador — mas continue lendo para entender por que ela funciona do jeito que funciona.
O que é o escape de strings JSON?
O escape de strings JSON é o processo de converter uma string bruta em uma forma segura para embutir dentro de um documento JSON. O JSON reserva um pequeno conjunto de caracteres que carregam significado estrutural: as aspas duplas " delimitam uma string, e a contrabarra \ inicia uma sequência de escape. Os caracteres de controle abaixo de U+0020, como quebras de linha, tabulações e retornos de carro, também não podem aparecer literalmente dentro de uma string JSON. O escape substitui cada um deles por uma sequência segura para que a string resultante seja analisada corretamente.
Quando você realmente precisa disso? Algumas situações aparecem o tempo todo:
- JSON-em-JSON: um envelope de webhook, uma mensagem Kafka ou um log de auditoria guarda o corpo de uma requisição como campo de string, então o JSON interno precisa ser escapado antes de poder ser atribuído.
- Configuração escrita à mão: jogar um script de shell, uma consulta SQL ou um trecho de código de várias linhas em um único valor JSON significa transformar cada quebra de linha em
\n. - Corpos de requisição REST: montar à mão um corpo JSON para o
curlou um cliente HTTP, onde aspas e quebras de linha precisam sobreviver ao shell e à rede. - Codificação segura para logs: gravar conteúdo fornecido pelo usuário em uma linha de log estruturada sem deixar que uma aspa ou quebra de linha injetada corrompa o formato.
Uma palavra rápida sobre a ordem das operações. Se você está partindo de um JSON bagunçado ou não confiável, valide-o primeiro para escapar algo bem formado — cole-o no Formatador JSON para formatar e conferir, depois escape o resultado limpo. Escapar lixo só dá lixo escapado.
Quais caracteres precisam de escape em JSON
A especificação JSON define uma lista precisa e curta. Sete caracteres têm um escape dedicado de dois caracteres, e todo o resto abaixo de U+0020 recai sobre um escape Unicode \uXXXX. Aqui está o conjunto completo de caracteres de escape JSON:
| Caractere | Escapa para | Observações |
|---|---|---|
" (U+0022) | \" | Delimitador de string |
\ (U+005C) | \\ | Início do escape (o caso da contrabarra de escape JSON) |
| quebra de linha (U+000A) | \n | |
| retorno de carro (U+000D) | \r | |
| tabulação (U+0009) | \t | |
| backspace (U+0008) | \b | |
| avanço de formulário (U+000C) | \f | |
| outros controles < U+0020 | \uXXXX | ex.: U+0000 → \u0000 |
O que não precisa de escape é igualmente importante. A barra / é um caractere perfeitamente normal (escapá-la é opcional, e só é útil em um caso bem específico abordado adiante). Aspas simples nunca precisam de escape porque o JSON não as usa como delimitadores. E todo caractere imprimível em U+0020 ou acima — incluindo todos os caracteres UTF-8 de múltiplos bytes como é, 日 ou 😀 — é válido como está.
Aqui está a diferença na prática. A entrada bruta à esquerda, o literal de string JSON escapado à direita:
Input:
She said "hello" then left.
Escaped:
"She said \"hello\"\tthen left."
As aspas duplas viraram \" e a tabulação virou \t. Agora a string está segura para ser colocada em qualquer parser JSON, linha de log ou corpo de requisição.
JSON Escape vs JSON Stringify: qual é a diferença?
Este é o ponto que a maioria dos tutoriais pula, e confunde muita gente. Escapar e JSON.stringify não são duas operações diferentes — são duas visões da mesma coisa.
JSON.stringify(value) serializa qualquer valor JavaScript em sua representação textual JSON. Quando esse valor é uma string, serializá-la significa envolvê-la em aspas duplas e escapar os caracteres especiais lá dentro. Isso é exatamente o escape JSON. Então JSON.stringify("a\tb") retorna a string de sete caracteres "a\tb", aspas incluídas.
A questão prática é se você quer essas aspas externas ou não. Isso mapeia diretamente para a opção Envolver em aspas duplas da ferramenta Escape JSON:
| Modo | Saída para a entrada a"b | Quando usar |
|---|---|---|
| Envolver ativado | "a\"b" | Um literal de string JSON completo, idêntico ao JSON.stringify. Atribua a uma variável ou cole depois de dois-pontos. |
| Envolver desativado | a\"b | Apenas o corpo escapado, sem as aspas ao redor. Use quando você mesmo está digitando as aspas em um documento JSON. |
Então, se você pesquisou por “json stringify” e chegou aqui, o modelo mental é simples: aplicar stringify a uma string = escape com envolver ativado. A forma sem aspas é a mesma coisa com as aspas externas removidas.
Como escapar uma string para JSON no código
A regra de ouro: nunca monte à mão uma corrente de chamadas replace(). Toda linguagem de uso geral traz um serializador JSON que lida com aspas, contrabarras, caracteres de controle e Unicode corretamente. Recorra a ele.
JavaScript
const text = 'She said "hi"\nthen left.';
const escaped = JSON.stringify(text);
console.log(escaped);
// "She said \"hi\"\nthen left."
JSON.stringify em uma string dá o literal completo e com aspas. Quer só o corpo? Corte o primeiro e o último caractere: JSON.stringify(text).slice(1, -1).
Python
import json
text = 'She said "hi"\nthen left.'
print(json.dumps(text))
# "She said \"hi\"\nthen left."
print(json.dumps(text, ensure_ascii=False))
# "She said \"hi\"\nthen left." (não-ASCII mantido como UTF-8)
json.dumps usa por padrão ensure_ascii=True, que escapa todo caractere não-ASCII para \uXXXX — o mesmo comportamento do modo ASCII-seguro da ferramenta. Passe ensure_ascii=False para manter o UTF-8 bruto.
PHP
<?php
$text = "café \"quoted\"\nline";
echo json_encode($text);
// "caf\u00e9 \"quoted\"\nline" (por padrão escapa não-ASCII para \uXXXX)
echo json_encode($text, JSON_UNESCAPED_UNICODE);
// "café \"quoted\"\nline"
json_encode escapa tanto caracteres não-ASCII quanto barras por padrão. Adicione JSON_UNESCAPED_UNICODE para manter os acentos legíveis, e JSON_UNESCAPED_SLASHES para deixar o / em paz.
Go e Java
Em Go, json.Marshal(text) retorna os bytes escapados e com aspas:
b, _ := json.Marshal(`a "quoted" line`)
// b == `"a \"quoted\" line"`
Em Java, objectMapper.writeValueAsString(text) do Jackson ou JSONObject.quote(text) do org.json produzem o mesmo literal com aspas. Seja qual for a linguagem, apoie-se na biblioteca — ela já conhece cada caso extremo que você esqueceria.
Embutindo JSON dentro de JSON (JSON-em-JSON)
Este é o motivo mais comum para as pessoas escaparem JSON à mão. Um envelope de webhook, um registro de fila de mensagens ou um log de auditoria muitas vezes guarda um corpo de requisição inteiro como campo de string. Para fazer isso, o JSON interno precisa ser escapado antes.
Veja um pequeno objeto passar por duas camadas de codificação:
1. Inner object: {"a":1}
2. Escaped as a string: "{\"a\":1}"
3. Placed in envelope: {"payload": "{\"a\":1}"}
Cada " do objeto interno virou \", e o conjunto todo foi envolvido em um par externo de aspas. O resultado é um único valor de string válido que você pode atribuir a payload.
O detalhe do aninhamento mais profundo é que as contrabarras se multiplicam. Escapar uma string já escapada também escapa suas contrabarras, então cada camada quase dobra o número delas: uma aspa interna que era \" vira \\\" um nível acima, e \\\\\" mais um nível acima. JSON-em-JSON com três níveis de profundidade fica difícil de ler de cabeça, e aí uma ferramenta poupa o trabalho. Para ir na direção oposta e tirar o objeto interno de volta de dentro da string, passe-a pela nossa ferramenta Des-escape de JSON.
Unicode e escape \uXXXX
Por padrão, o JSON fica feliz com UTF-8 bruto. Um é continua um é, um 日 continua um 日, e o documento fica mais legível por isso. Você não precisa escapar nenhum caractere Unicode imprimível.
Então, quando você recorreria à saída ASCII-segura \uXXXX? Apenas quando um sistema a jusante não pode receber UTF-8 com confiança: gateways SOAP ou XML antigos, certos pipelines de logging, cabeçalhos de e-mail ou arquivos-fonte que precisam permanecer puramente ASCII. No modo ASCII-seguro, todo caractere acima de U+007F vira um escape \uXXXX — café se transforma em caf\u00e9. Fica mais barulhento, mas é ASCII byte a byte, e decodifica de volta para o original em qualquer parser compatível.
Há uma sutileza. \uXXXX codifica uma única unidade de código UTF-16 de 16 bits, mas caracteres fora do Plano Multilíngue Básico — emoji, escritas raras — precisam de 21 bits. O JSON lida com eles por meio de um par substituto (surrogate pair): dois escapes \uXXXX lado a lado. Uma carinha sorridente 😀 (U+1F600) vira \ud83d\ude00. A maioria dos serializadores faz isso por você; o perigo é um escapador escrito à mão que emite um substituto solitário e sem par.
Se pares substitutos e pontos de código forem território novo, o Guia UTF-8 vs UTF-16 vs Unicode detalha exatamente como um único caractere mapeia para bytes e unidades de código. É o contexto que falta por trás do motivo de um emoji precisar de dois escapes.
Des-escape: lendo de volta o JSON escapado
O escape tem um inverso. Para transformar "a\tb" de volta no texto real com duas linhas ou tabulado, você o analisa: JSON.parse(str) em JavaScript, json.loads(str) em Python. O parser percorre cada sequência de escape e reconstrói os caracteres originais, pares substitutos incluídos.
Quando o des-escape falha, o erro é quase sempre “invalid escape sequence”, e ele tem algumas causas comuns:
- Uma contrabarra solitária antes de um caractere que o JSON não reconhece como escape, como
\q. - Um escape inventado como
\x41— o JSON não tem o escape hexadecimal\x; ele só usa\u. - Um escape
\utruncado com menos de quatro dígitos hexadecimais, como\u00. - Uma aspa dupla solta ou desbalanceada que quebra o limite da string.
Verifique se toda contrabarra inicia um dos escapes válidos (\n \r \t \b \f \" \\ \/ \uXXXX) e se as aspas estão pareadas. Para strings escapadas copiadas do meio de uma linha de log — onde as aspas externas ficaram para trás — nossa ferramenta Des-escape de JSON aceita o corpo com ou sem aspas ao redor e o decodifica de qualquer forma.
Armadilhas comuns ao escapar JSON
A maioria dos payloads quebrados remonta a um destes seis erros.
1. Escape duplo. Escapar um texto que já estava escapado transforma \n em \\n e \" em \\\", então o consumidor lê uma contrabarra-n literal em vez de uma quebra de linha. Isso costuma acontecer quando um serviço a montante já escapou o valor em JSON e você escapa de novo. Faça o des-escape primeiro para checar o estado atual, depois escape exatamente uma vez.
2. Esquecer as aspas externas. Com envolver desativado você obtém só o corpo escapado, não uma string completa. Colar hello \"world\" diretamente onde se espera um valor JSON é inválido porque faltam as aspas ao redor. Ou mantenha o envolver ativado ou digite as aspas você mesmo.
3. Escape excessivo de não-ASCII. Ligar o modo ASCII-seguro quando o consumidor lida bem com UTF-8 só incha a saída. café vira caf\u00e9 sem motivo: fica mais difícil de ler e mais pesado na rede, sem nenhum ganho. Deixe desligado a menos que um sistema legado específico exija ASCII puro.
4. Escapar a barra por reflexo. O escape do / importa em exatamente um lugar: JSON embutido dentro de uma tag HTML <script>, onde a substring </script> fecharia a tag cedo demais independentemente do contexto JSON. Escapar / para \/ neutraliza isso. Fora desse único caso, escapar barras só adiciona ruído, então deixe desligado para corpos REST, arquivos de configuração e payloads de mensagens.
5. Correntes de replace feitas à mão. Um pipeline manual replace('"', '\\"') quase sempre esquece de algo — um caractere de controle, um backspace, um par substituto. Use o serializador da linguagem, que cobre a especificação inteira.
6. Escapar mas nunca des-escapar (ou des-escapar duas vezes). Uma ida e volta precisa estar equilibrada. Escape uma vez na entrada, des-escape uma vez na saída. Des-escape duas vezes e você estraga contrabarras reais que faziam parte dos dados.
Mais uma distinção que vale fixar: o escape JSON não é codificação de URL nem codificação por porcentagem. Eles resolvem problemas diferentes para transportes diferentes, e misturá-los (codificar um valor por porcentagem e depois escapá-lo em JSON, ou vice-versa) produz uma bagunça que nenhum dos parsers consegue ler direito. O Guia de codificação e decodificação de URL cobre quando a codificação por porcentagem é a ferramenta certa e como ela difere do que o JSON faz.
Perguntas frequentes
O que significa escapar uma string em JSON?
Significa substituir os caracteres que carregam significado estrutural para o JSON — as aspas duplas, a contrabarra e caracteres de controle como quebra de linha e tabulação — por sequências de escape seguras como \", \\ e \n. O resultado pode ser embutido como literal de string dentro de um documento JSON sem quebrar a análise.
Quais caracteres precisam de escape em JSON?
As aspas duplas, a contrabarra, a quebra de linha, o retorno de carro, a tabulação, o backspace e o avanço de formulário cada um recebe um escape dedicado, e todo outro caractere de controle abaixo de U+0020 vira \uXXXX. Caracteres imprimíveis e UTF-8 de múltiplos bytes não precisam de escape; a barra é opcional e só importa dentro de tags HTML <script>.
O escape JSON é o mesmo que JSON.stringify?
São duas visões da mesma operação. JSON.stringify aplicado a uma string a envolve em aspas duplas e escapa os caracteres especiais lá dentro, e isso é o escape JSON. Envolver ativado equivale à forma com aspas (idêntica ao JSON.stringify); envolver desativado dá só o corpo escapado sem as aspas ao redor.
Como escapo uma string para JSON em JavaScript ou Python?
Em JavaScript use JSON.stringify(str); em Python use json.dumps(str). Sempre confie na função embutida em vez de uma corrente de replace escrita à mão — as embutidas lidam corretamente com Unicode, caracteres de controle e todo caso extremo que você senão deixaria passar.
Por que meu JSON quebra com contrabarras a mais?
A causa habitual é o escape duplo: escapar um texto que já estava escapado, então \n vira \\n e o consumidor lê uma contrabarra-n literal em vez de uma quebra de linha. Faça o des-escape do valor primeiro para checar seu estado real, depois escape-o exatamente uma vez.
Preciso escapar barras ou Unicode em JSON?
Nenhum dos dois é obrigatório. A / é um caractere normal e só precisa de escape quando você embute JSON dentro de uma tag HTML <script>, para impedir que a sequência </script> a feche cedo demais. O Unicode permanece como UTF-8 bruto por padrão; use \uXXXX apenas quando um sistema a jusante não consegue lidar com UTF-8.