JSON inválido — os erros mais comuns e como achar cada um rápido
Vírgula final, aspas simples, comentários, chaves sem aspas e outros motivos para um JSON ser recusado, com a correção exata de cada um.
Por Felipe YamaokaPublicado em 5 de novembro de 20265 min de leitura
"Unexpected token" na pior hora
Um deploy falha porque um arquivo de configuração não carrega. Uma API devolve 400 e a única pista é Unexpected token } in JSON at position 1843. Você abre o arquivo, parece tudo certo, e começa a contar chaves.
O JSON é um formato pequeno de propósito, e é justamente por isso que ele recusa coisas que parecem inofensivas para quem também escreve JavaScript, Python ou YAML. Quase todo documento inválido cai num punhado de erros. Este guia lista cada um, mostra como ele aparece e como corrigir, para a próxima mensagem de erro levar segundos e não minutos.
O que o JSON realmente aceita
O formato inteiro, definido na RFC 8259, cabe em poucas regras:
- Um valor é um objeto, um array, uma string, um número,
true,falseounull. - As chaves de objeto são sempre strings entre aspas duplas.
- Strings usam só aspas duplas, e alguns caracteres dentro delas precisam de escape.
- Os itens de objetos e arrays são separados por vírgula, e não existe vírgula depois do último.
- Números são decimais: sem zero à esquerda, sem
NaN, semInfinity, sem hexadecimal. - Não existem comentários.
Tudo o que vem a seguir quebra uma dessas regras.
1. Vírgula final
É de longe o erro mais frequente, porque JavaScript, TypeScript e Python aceitam:
{
"name": "api",
"port": 8080,
}Tire a vírgula depois do último item. O mesmo vale para arrays: [1, 2, 3,] é inválido. O Formatador JSON mostra "Vírgula final não é permitida" e aponta a linha e a coluna da chave de fechamento, que é onde o parser percebe o problema.
2. Aspas simples
{ 'name': 'api' }Strings e chaves em JSON precisam de aspas duplas. Troque ' por ". Se o próprio texto tiver aspas duplas, use escape: "Ele disse \"oi\"".
3. Chaves sem aspas
{ name: "api" }Isso é JavaScript válido, mas não é JSON. Toda chave precisa ser uma string entre aspas: { "name": "api" }.
4. Comentários
{
"port": 8080 // porta padrão
}JSON não tem comentários, nem // nem /* */. Arquivos como o tsconfig.json e as configurações do VS Code aceitam porque essas ferramentas usam uma variante mais flexível chamada JSONC, mas um parser padrão, como o JSON.parse ou a maioria das APIs, recusa. Se você precisa de anota ções na configuração, use um campo como "_comment" ou troque por um formato que aceita comentários, como YAML ou TOML.
5. Números inválidos
Todos estes são recusados:
{ "a": 01 } zero à esquerda
{ "a": .5 } falta o dígito antes do ponto
{ "a": NaN } não existe em JSON
{ "a": Infinity } não existe em JSON
{ "a": 0x1F } sem hexadecimalEscreva 1, 0.5 e 31. Para valores que o JSON não representa, como NaN, use null ou uma string e trate no código. E lembre que o separador decimal é sempre o ponto: { "preco": 19,90 } é erro, e [19,90] vira dois números, 19 e 90.
Uma armadilha parecida é de precisão, e não de validade. 12345678901234567890 é JSON válido, mas o JSON.parse do JavaScript transforma em 12345678901234567000, porque números acima de 2 elevado a 53 perdem dígitos como double. IDs de outros sistemas, como códigos de transação bancária ou ids de tweets, deveriam trafegar como string. O Formatador JSON deste site preserva os dígitos originais ao reformatar, então é um jeito seguro de olhar esse tipo de payload.
6. Quebra de linha e caracteres de controle dentro de strings
{ "message": "primeira linha
segunda linha" }Uma quebra de linha crua dentro da string não é permitida. Use o escape \n: "primeira linha\nsegunda linha". O mesmo vale para tab (\t) e outros caracteres de controle. Isso costuma aparecer quando alguém monta o JSON concatenando texto em vez de usar um serializador.
7. Conteúdo depois do fim
{ "a": 1 }}ou dois documentos grudados:
{ "a": 1 }
{ "b": 2 }Um documento JSON tem exatamente um valor no nível de cima. Uma chave a mais geralmente vem de uma edição mal feita. Vários objetos, um por linha, é outro formato, o JSON Lines (NDJSON), que precisa ser lido linha a linha.
8. O documento termina antes da hora
{ "items": [1, 2, 3Falta um ] ou um } no fim, muitas vezes porque a linha de log foi cortada ou a resposta veio pela metade. A posição do erro vai ser o finalzinho do texto. Confira se você tem o payload inteiro antes de procurar um erro de digitação.
Como achar o erro rápido
- Leia a posição, não só a mensagem. O parser informa onde desistiu, o que normalmente é logo depois do erro de verdade. Olhe a linha anterior.
- Formate o documento. Com indentação, uma vírgula faltando ou uma chave a mais saltam aos olhos. Um formatador que mostra "linha 12, coluna 3" poupa você de contar caracteres.
- Gere JSON, não escreva na mão. O
JSON.stringifydo JavaScript, ojson.dumpsdo Python e os serializadores de qualquer linguagem nunca cometem esses erros. - Valide na fronteira. Quando o seu código recebe JSON, faça o parse uma vez, informe o erro com a posição e pare, em vez de deixar um objeto lido pela metade circular pelo sistema.
No JavaScript, um parse seguro com mensagem clara fica assim:
function parseJson(text) {
try {
return { ok: true, value: JSON.parse(text) };
} catch (error) {
return { ok: false, message: error.message };
}
}Os erros comuns, numa lista só
- Vírgula depois do último item de um objeto ou array.
- Aspas simples em vez de duplas.
- Chaves sem aspas.
- Comentários copiados de um arquivo JSONC ou JavaScript.
- Números com zero à esquerda, vírgula decimal,
NaNouInfinity. - Quebras de linha cruas dentro de strings.
- Conteúdo a mais depois da chave de fechamento.
- Documentos cortados.
Resumo
O JSON é rígido de propósito: aspas duplas em tudo, nada de vírgula final, nada de comentário e números decimais simples. Quando o parser reclamar, leia a linha e a coluna, olhe logo antes desse ponto e confira a lista acima; em nove de cada dez casos a correção é um caractere. E, sempre que puder, deixe um serializador escrever o JSON por você.
Leia também
Base64 não é criptografia — o que é, quando usar e a variante URL-safe
Como o Base64 transforma bytes em texto, por que ele não esconde nada, como tratar acentos e emoji do jeito certo e quando usar o alfabeto URL-safe.
5 de novembro de 20265 min de leituraFerramenta: Codificador/Decodificador Base64
A regex que trava o navegador — backtracking catastrófico explicado
Por que uma expressão regular curta pode levar segundos ou travar a página, como reconhecer quantificadores aninhados e como reescrever o padrão.
5 de novembro de 20266 min de leituraFerramenta: Testador de Regex