Todos os artigos
52 artigos · atualizado semanalmente Veja nossas Ferramentas
Todos os artigos
Tutoriais

Como validar JSON e encontrar erros de sintaxe

Trailing comma, aspas simples, chave sem fechar — os erros de sintaxe JSON mais comuns e como localizar a linha exata sem adivinhar.

COVER · Tutoriais

A API retornou 400. O log diz Unexpected token. Você olha o payload, parece certo. Você abre o browser, cola no DevTools, JSON.parse(...) — mesmo erro. Aí começa o jogo de procurar uma vírgula fora de lugar numa string de 300 linhas minificada.

Esse ritual é mais comum do que deveria ser. Este post é sobre encurtar ele ao máximo.

Os erros de sintaxe JSON que aparecem o tempo todo

JSON tem uma gramática pequena e rígida. Não tem comentários, não tem trailing comma, não aceita aspas simples, não tolera undefined. Qualquer desvio e o parser para imediatamente.

Os erros que mais aparecem na prática:

Trailing comma (vírgula no último item)

{
  "name": "Rafael",
  "role": "dev",
}

A vírgula depois de "dev" é inválida. JSON não aceita trailing comma — diferente de JavaScript, onde isso funciona. O erro costuma aparecer quando você remove uma linha do meio de um objeto e esquece de ajustar a vírgula do penúltimo item.

Aspas simples em vez de aspas duplas

{
  'name': 'Rafael'
}

JSON exige aspas duplas. Aspas simples são JavaScript, YAML, Python — não JSON. O erro é sutil visualmente, especialmente se você está acostumado a escrever objetos JS no dia a dia.

Chave sem aspas

{
  name: "Rafael"
}

Novamente: válido em JS, inválido em JSON. Toda chave precisa de aspas duplas, sem exceção.

Vírgula faltando entre propriedades

{
  "name": "Rafael"
  "role": "dev"
}

Parser vai tentar ler "role" como continuação de "Rafael" — e falha. Esse é o erro que aparece quando você adiciona um campo novo num objeto grande e esquece de colocar vírgula no fim da linha anterior.

Colchetes ou chaves não fechados

{
  "items": [
    {"id": 1},
    {"id": 2}
  
}

Falta fechar o ]. O parser chega no } e não encontra o que espera. Em JSONs aninhados profundos, achar o ponto exato onde o colchete sumiu é o que torna esse erro especialmente irritante.

Valor undefined ou comentário

{
  "debug": undefined,
  // configuração temporária
  "timeout": 30
}

undefined não é um valor válido em JSON (use null). Comentários também não existem em JSON — use // num arquivo .json e o parser quebra. Se precisar de comentários, considere JSONC (JSON with Comments), que editores como VS Code entendem mas que parsers padrão rejeitam.


Como localizar a linha do erro sem adivinhar

O erro Unexpected token ',' at position 142 não é muito útil quando o arquivo tem 2000 caracteres. Mas quase todos os parsers e ferramentas dão informação de linha e coluna — o problema é saber onde olhar.

No browser (DevTools):

try {
  JSON.parse(seuJson);
} catch (e) {
  console.log(e.message);
  // SyntaxError: Unexpected token '}' at position 89
}

A posição é em caracteres a partir do início da string. Não é diretamente a linha, mas você pode usar um editor para ir até o caractere 89. No VS Code: Ctrl+G para ir para linha, ou no terminal echo "seuJson" | python3 -m json.tool mostra linha e coluna.

No Python:

import json

try:
    data = json.loads(texto)
except json.JSONDecodeError as e:
    print(f"Erro na linha {e.lineno}, coluna {e.colno}: {e.msg}")

JSONDecodeError herda de ValueError e expõe lineno, colno e doc (a string original). Você consegue extrair o trecho exato com e.doc.split('\n')[e.lineno - 1].

No Node.js:

try {
  JSON.parse(texto);
} catch (e) {
  // e.message tem posição, mas não linha diretamente
  // Alternativa: usar um parser que dê linha/coluna
  const lines = texto.split('\n');
  // calcular linha a partir da posição no e.message
}

O JSON.parse nativo do Node não expõe linha/coluna diretamente — só posição em caracteres. Para obter linha e coluna precisas, ferramentas de lint ou validators externos são mais úteis.


Validar JSON online: quando faz sentido

Para payloads grandes ou quando você está debugando um arquivo que chegou de fora (resposta de API, export de banco, arquivo de configuração), um validador online poupa tempo. Você cola, ele aponta a linha exata.

Uso o JSON Formatter pra isso — em especial quando preciso formatar antes de inspecionar, porque JSON minificado numa linha só é ilegível mesmo pra um diff. O validador mostra o erro com linha e coluna, e dá pra navegar pela estrutura antes de corrigir.

Se o JSON está minificado, formatar primeiro é quase obrigatório. Tentar encontrar uma trailing comma em {"name":"a","role":"b",} é trivial, mas em 50KB numa linha só, não.


Validar contra schema: além da sintaxe

Sintaxe válida não quer dizer dado correto. Um JSON pode parsear sem erro e ainda assim estar errado para a sua aplicação: campo obrigatório ausente, tipo errado ("age": "trinta"), valor fora do range esperado.

Para esse nível de validação, você precisa de JSON Schema. Se quiser entender a estrutura do formato antes de aprofundar em schema, tem um post mais intro em O que é JSON e como funciona.

Um schema básico que valida tipo e campos obrigatórios:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["name", "age"],
  "properties": {
    "name": { "type": "string" },
    "age": { "type": "integer", "minimum": 0 }
  }
}

Contra esse schema, o payload {"name": "Rafael", "age": "trinta"} falha com must be integer no campo age. A sintaxe está correta — o tipo está errado.

Ferramentas como AJV (JavaScript), jsonschema (Python) ou opis/json-schema (PHP) fazem essa validação programaticamente. Para testar um schema antes de integrar no código, um validator online com suporte a JSON Schema resolve sem precisar subir nada.


JSON em arquivos de configuração: armadilhas específicas

Arquivos .json de configuração (package.json, tsconfig.json, appsettings.json) têm algumas peculiaridades que causam erros:

tsconfig.json aceita comentários, package.json não. O TypeScript usa JSONC internamente, então comentários em tsconfig.json funcionam no VS Code e no compilador. Mas se você pegar aquele arquivo e tentar parsear com JSON.parse no seu código, vai quebrar.

Números grandes viram float. JSON não tem distinção entre integer e float na spec — é tudo number. Números maiores que 2^53 - 1 perdem precisão ao serem parseados em JavaScript porque não cabem num float64. Se você está trabalhando com IDs grandes (como IDs do Twitter/X), isso é um problema real. A solução é trafegar esses valores como string.

Chaves duplicadas são "válidas" mas perigosas. A spec JSON não proíbe chaves duplicadas num objeto. O comportamento é indefinido — parsers diferentes resolvem diferente. Alguns usam o último valor, outros o primeiro, outros retornam erro. Não confie em chaves duplicadas para nenhuma lógica.


Perguntas frequentes

Por que JSON não aceita trailing comma?

Porque a spec do JSON (RFC 8259) foi desenhada para ser simples e sem ambiguidade. Trailing comma complica o parsing e cria casos especiais. A escolha foi manter a gramática mínima. Se você quer trailing comma, use JavaScript (onde é válido), YAML, ou JSONC — que é uma extensão não-oficial do JSON que adiciona comentários e trailing commas, usada pelo VS Code e TypeScript.

Como validar JSON em linha de comando sem instalar nada?

Se você tem Python instalado (qualquer sistema Unix/Mac tem por padrão):

echo '{"name": "test",}' | python3 -m json.tool
# Expecting property name enclosed in double quotes: line 1 column 18 (char 17)

Com Node.js:

node -e "JSON.parse(require('fs').readFileSync('arquivo.json', 'utf8'))"

Com jq (se instalado):

cat arquivo.json | jq .

jq é o mais informativo — mostra linha e coluna do erro com contexto visual.

O que é a diferença entre JSON inválido e JSON mal-formado?

Na prática, são sinônimos. Tecnicamente, "mal-formado" se refere a violações da gramática (trailing comma, aspas erradas) e "inválido" pode incluir violações de schema ou semântica. Mas na maioria das conversas técnicas e mensagens de erro, os termos são usados de forma intercambiável.

JSON Schema serve para validar qualquer JSON?

Sim, mas com uma ressalva: JSON Schema define um contrato, e você precisa escrever esse contrato. Ele não infere automaticamente o que é correto para o seu caso — você declara o que espera (tipos, campos obrigatórios, ranges, padrões de string) e o validator aplica. Para payloads arbitrários onde você só quer verificar sintaxe, JSON.parse já é suficiente.


Sintaxe correta é condição necessária, não suficiente

JSON válido sintaticamente é só o começo. O parser aceitar o dado não significa que a aplicação vai aceitar. A sequência correta é: validar sintaxe primeiro (JSON.parse ou qualquer validator), depois validar schema se o dado vier de fora do seu controle (API externa, input de usuário, arquivo de configuração gerenciado por outro time).

Para dados internos que você mesmo produz, testes de integração que verificam o contrato são mais úteis do que schema em runtime — porque o problema geralmente está na serialização, não no input.

O erro de sintaxe é o mais fácil de corrigir. O Unexpected token nunca é ambíguo: tem algo errado naquele ponto, e qualquer parser ou validator mostra onde. A parte difícil é quando o JSON parseia sem erro mas o dado está semanticamente errado — e aí você precisa de schema.


Nota: o conteúdo editorial acabou aqui. O que vem abaixo é uma indicação de ferramenta relacionada ao tema do post.


Ferramenta relacionada

Para validar e formatar JSON sem sair do browser — incluindo localizar a linha exata do erro de sintaxe — uso o JSON Formatter. Funciona offline, não envia o dado a lugar nenhum, e formata antes de validar para tornar a estrutura legível.

RD
Autor
Rafael Duarte
Desenvolvedor backend com passagem por fintech e SaaS B2B — trabalhou em times que escalaram APIs de zero a milhões de requisições. Carrega cicatrizes de produção suficientes para ter opiniões fortes sobre ferramentas, padrões e decisões de arquitetura. Não é acadêmico: leu a RFC do UUID quando precisou escolher entre v4 e v7 para uma tabela de alta escrita.
Ver perfil