← Todos os artigos

Como lidar com JSON quebrado em JavaScript

JSON do mundo real costuma vir sujo: vírgulas finais, aspas simples, literais Python, fences de markdown. Aprenda padrões comuns, como escrever um helper de parse seguro e quando ir para uma biblioteca de reparo dedicada.

Todo dev JavaScript já viu: JSON.parse() lança um SyntaxError e sua aplicação quebra. O JSON veio de uma API, um arquivo de config ou do clipboard do usuário —— e simplesmente não parseia. Neste guia vamos passar exatamente por que isso acontece, como JSON quebrado se parece no mundo real, e como lidar com isso de forma elegante —— de um simples try/catch até reparo automático.

1. Por que JSON.parse() falha

O padrão JSON (RFC 8259) é deliberadamente estrito. JSON.parse() implementa isso ao pé da letra —— qualquer desvio, por menor que seja, lança um SyntaxError sem recuperação parcial:

try {
  const data = JSON.parse('{ name: "Ada" }'); // key sem aspas
} catch (err) {
  console.error(err.message);
  // SyntaxError: Expected property name or '}' in JSON at position 2
}

Diferente de um navegador parseando HTML (que tem um modelo de recuperação de erro embutido), o parser JSON é um portão duro. Parsing estrito é uma feature: força produtores a emitir dado limpo. Mas quando você não controla a fonte do dado —— saída de LLM, arquivos de config editados à mão, APIs de terceiros —— você precisa de uma estratégia pra quando esse portão fechar com força.

2. Os padrões mais comuns de JSON quebrado

Antes de partir pra uma biblioteca de reparo, ajuda reconhecer com o que você está lidando. Quase todo JSON quebrado no mundo real cai numa dessas categorias:

Aspas simples em vez de duplas

// ❌ JSON inválido
{ 'name': 'Ada Lovelace' }

// ✅ Válido
{ "name": "Ada Lovelace" }

Literais de objeto JavaScript aceitam aspas simples; JSON não. Devs copiam um literal de objeto direto pra um contexto JSON e batem nesse erro constantemente.

Vírgulas no final

// ❌ JSON inválido
{
  "name": "Ada",
  "active": true,   // vírgula no final
}

// ✅ Válido
{
  "name": "Ada",
  "active": true
}

JavaScript moderno permite vírgulas no final em arrays e objetos. JSON não. Esse é o erro mais comum em arquivos JSON editados à mão.

Keys de objeto sem aspas

// ❌ JSON inválido
{ name: "Ada", score: 98 }

// ✅ Válido
{ "name": "Ada", "score": 98 }

Literais de objeto JavaScript não exigem keys com aspas. JSON exige que todas as keys sejam strings entre aspas duplas, sem exceções.

Comentários JavaScript

// ❌ JSON inválido
{
  // este é o registro do usuário
  "name": "Ada",
  /* adicionado em 2024 */
  "active": true
}

JSON não tem sintaxe de comentários. Comentários às vezes são adicionados a arquivos de config (JSONC —— JSON-com-Comentários —— é uma extensão popular), mas o JSON.parse() vai rejeitar.

Strings multilinha

// ❌ JSON inválido
{
  "description": "line one
  line two"
}

// ✅ Válido —— escape a quebra de linha
{
  "description": "line one\nline two"
}

Valores de string em JSON precisam estar numa única linha. Quebras de linha literais dentro de uma string não são permitidas; use a sequência de escape \n em vez disso.

NaN, Infinity e undefined

// ❌ Não é JSON válido
{ "ratio": NaN, "limit": Infinity, "value": undefined }

// ✅ Alternativas válidas
{ "ratio": null, "limit": 1e308, "value": null }

Esses são valores JavaScript válidos mas não fazem parte da especificação JSON. JSON.stringify() silenciosamente converte (NaN e Infinity viram null; propriedades undefined são totalmente descartadas), o que pode causar bugs sutis de round-trip.

Literais Python

// ❌ Estilo Python —— JSON inválido
{ "active": True, "deleted": False, "value": None }

// ✅ JSON válido
{ "active": true, "deleted": false, "value": null }

JSON foi projetado pra interoperar entre múltiplas linguagens. Os True, False e None com letra maiúscula do Python são uma fonte frequente de bugs de dados entre linguagens.

3. «Reparar» e «parsear» não são a mesma coisa

É importante distinguir entre duas operações fundamentalmente diferentes:

  • Parsing estrito —— validar que a entrada é JSON exatamente correto, reportar a localização precisa de qualquer erro, rejeitar qualquer coisa que desvie. Use quando você controla o produtor do dado e quer impor um contrato.
  • Parsing com reparo —— tentar recuperar um valor JSON válido de uma entrada sintaticamente imperfeita usando um conjunto de regras heurísticas. Use quando o dado vem de uma fonte não confiável ou imprecisa (saída de LLM, clipboard do usuário, serviço legado).

Um parser de reparo faz suposições. Se encontra True, assume que você quis dizer true. Se encontra uma vírgula no final, remove. Essas suposições quase sempre estão corretas pros padrões listados acima —— mas podem mascarar silenciosamente um documento genuinamente malformado onde o «conserto» muda o significado pretendido.

A ferramenta certa depende do contexto. Numa pipeline de respostas de API validadas por schema, você quer parsing estrito pra dado ruim aparecer imediatamente. Numa ferramenta de dev onde um humano está colando JSON copiado de uma mensagem do Slack, parsing com reparo economiza tempo.

Bibliotecas que vale conhecer

Dois pacotes npm fazem a maior parte do trabalho pesado, com trade-offs complementares:

  • jsonrepair —— um parser de reparo tolerante. Entrega JSON ruim e recebe uma string válida de melhor esforço de volta. Lida com os padrões acima (aspas simples, vírgulas no final, keys sem aspas, comentários, literais Python, fences de markdown, colchetes não fechados, input parcial). Síncrono, sem dependências, pequeno —— ideal quando você tem um documento completo na memória.
  • clarinet —— um parser JSON streaming estilo SAX. Use quando o JSON chega em chunks (um stream, um arquivo grande, uma resposta de LLM token por token) e você precisa reagir conforme keys/valores aparecem em vez de esperar o documento completo. É estrito sobre sintaxe, então combine com jsonrepair se a fonte for não confiável.

Regra geral: repare quando tem um blob pequeno e não confiável; stream quando o documento é grande ou chega progressivamente.

4. Pegando erros e dando feedback amigável aos usuários

O padrão mínimo viável é um try/catch. Sempre faça isso —— nunca deixe JSON.parse() lançar sem ser pego:

function safeParseJson(text) {
  try {
    return { ok: true, value: JSON.parse(text) };
  } catch (err) {
    return { ok: false, error: err.message };
  }
}

const result = safeParseJson(userInput);
if (!result.ok) {
  showError(`Could not parse JSON: ${result.error}`);
}

A mensagem de erro do JSON.parse() varia por engine JavaScript. V8 (Node.js, Chrome) inclui uma dica de posição:

// Mensagem de erro do V8
"Expected ',' or '}' after property value in JSON at position 42"

// Firefox SpiderMonkey
"JSON.parse: expected ',' or '}' after property value in object
at line 3 column 5 of the JSON data"

A informação de posição é útil mas específica de engine. Se você precisa de reporte confiável de linha/coluna entre ambientes, um parser de descida recursiva customizado pode emitir erros estruturados muito mais fáceis de exibir aos usuários.

5. Quando reparar automaticamente vs. pedir confirmação

Nem todos os reparos carregam o mesmo risco. Aqui uma heurística prática:

  • Seguro pra reparar automaticamente —— vírgulas no final, normalização de espaço em branco, conversão de estilo de aspas, keys sem aspas, comentários JavaScript, literais boolean/null Python. São transformações mecânicas sem ambiguidade semântica.
  • Considere perguntar ao usuário —— reparos estruturais como auto-fechar um objeto ou array não fechado ({"name": "Ada"{"name": "Ada"}), ou remover conteúdo (apagar um comentário que parece intencional). O reparo provavelmente está certo, mas o usuário pode querer verificar.
  • Sempre sinalize, nunca conserte em silêncio —— coerções de tipo como NaN → null mudam o valor do dado. Mostre ao usuário o que mudou.

Uma boa UI de reparo mostra um diff: a entrada original à esquerda, a saída reparada à direita. O usuário pode confirmar que o conserto está correto antes de copiar ou enviar o resultado.

6. A vantagem de privacidade do processamento JSON no navegador

Quando você processa JSON localmente no navegador —— usando a engine JavaScript que já está rodando a página —— o dado nunca deixa a máquina do usuário. Isso importa mais do que devs costumam perceber:

  • API keys e credenciais —— devs regularmente colam payloads JSON contendo segredos. Uma ferramenta do lado servidor loga toda requisição.
  • PII e dados de saúde —— compliance com GDPR e HIPAA fica muito mais simples quando não há transferência de dado.
  • Dados corporativos —— muitas políticas de segurança proíbem colar dados internos em serviços web de terceiros.

Processamento no navegador te dá reparo JSON com risco zero: sem servidor, sem logs, sem retenção de dados. A computação acontece num <textarea> e uns poucos kilobytes de JavaScript.

Perguntas frequentes

Como lido com um erro de JSON.parse em JavaScript?

Envolva a chamada num try/catch e retorne um resultado estruturado em vez de deixar o SyntaxError propagar (veja o helper safeParseJson acima). Nunca chame JSON.parse() em input não confiável sem um guard.

Tem como parsear JSON quebrado automaticamente?

Tem —— um parser de reparo recupera um valor válido de input imperfeito aplicando heurísticas (remover vírgulas no final, converter aspas simples, deixar True em minúscula). Use pra fontes não confiáveis como saída de LLM ou texto colado, não pra respostas de API validadas por contrato onde você quer que dado ruim apareça.

Quando devo reparar JSON vs. rejeitá-lo?

Repare quando um humano colou JSON aproximado ou um LLM produziu; rejeite (parsing estrito) quando você controla o produtor e quer impor um schema. Coerções de tipo como NaN → null sempre devem ser sinalizadas, nunca aplicadas em silêncio.

Qual a causa mais comum de JSON quebrado?

Tratar um literal de objeto JavaScript como JSON —— aspas simples, keys sem aspas e vírgulas no final. Veja JSON vs objetos JavaScript e a referência de erros de sintaxe em [object Object] e outros erros.

7. Experimente agora —— cole seu JSON quebrado

Se você tem uma string JSON malformada que precisa consertar agora, o JSON Fix lida com todos os padrões acima —— aspas simples, vírgulas no final, keys sem aspas, literais Python, comentários, fences de código markdown e mais. Tudo roda no seu navegador; nada é enviado pra servidor.