← Todos os artigos

JSON vs objeto JavaScript: por que aspas simples não são permitidas

Muitos devs tratam literais de objeto JS como JSON. Não são a mesma coisa: aspas simples, chaves sem aspas, vírgulas finais, undefined, NaN — aqui cada diferença com exemplos.

Você cola o que parece dado válido num parser JSON e ele imediatamente lança SyntaxError: Unexpected token '''. O dado veio do seu código JavaScript e parece completamente razoável —— mas JSON e object literals do JavaScript não são o mesmo formato, e as diferenças importam mais do que a maioria dos desenvolvedores percebe.

A resposta curta: JSON não suporta aspas simples

Aspas simples são totalmente ilegais em JSON. Toda string —— tanto keys quanto valores —— precisa usar aspas duplas. Sem exceções.

// ❌ JSON inválido —— strings com aspas simples
{ 'name': 'Ada Lovelace', 'active': true }

// ✅ JSON válido
{ "name": "Ada Lovelace", "active": true }

O erro que você vai ver em diferentes ambientes:

// Chrome / Node.js (V8)
SyntaxError: Unexpected token "'", "{'name':..." is not valid JSON

// Firefox
SyntaxError: JSON.parse: unexpected character at line 1 column 2 of the JSON data

// Safari
SyntaxError: JSON Parse error: Single quotes (') are not allowed in JSON

A mensagem do Safari é a mais útil —— ela te diz exatamente qual é o problema. As outras só reportam o caractere inesperado.

Por que o JSON exige aspas duplas?

JSON foi definido por Douglas Crockford em 2001 e padronizado como RFC 8259. A gramática especifica exatamente um delimitador de string: o caractere aspas duplas (U+0022). Aspas simples simplesmente não estão na gramática.

A razão é simplicidade. JSON é um formato de troca de dados pensado pra ser parseado por qualquer linguagem, não só JavaScript. Ao impor um único estilo de aspas, a spec elimina uma classe inteira de ambiguidade. Parsers em Go, Python, Java, Rust e qualquer outra linguagem implementam exatamente a mesma regra.

JSON vs object literal do JavaScript: as diferenças completas

Aspas simples é só uma de várias diferenças. Eis o quadro completo:

1. Keys precisam ser strings entre aspas duplas

// ❌ Object literal do JavaScript —— key nua, key com aspas simples
{ name: "Ada", 'score': 98 }

// ✅ JSON —— todas as keys são strings entre aspas duplas
{ "name": "Ada", "score": 98 }

Object literals do JavaScript aceitam identificadores nus, strings entre aspas simples e strings entre aspas duplas como keys. JSON só aceita strings entre aspas duplas.

2. Sem vírgulas no final

// ❌ JSON inválido
{ "name": "Ada", "score": 98, }
//                            ^ vírgula no final

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

JavaScript moderno permite explicitamente vírgulas no final. JSON não —— veja nosso guia completo sobre vírgulas no final em JSON.

3. Sem comentários

// ❌ JSON inválido
{
  // perfil do usuário
  "name": "Ada"
}

// ✅ JSON não tem sintaxe de comentários
{ "name": "Ada" }

JSON não tem nenhuma sintaxe de comentários. Se você precisa de comentários em arquivos de config, considere o formato JSONC (JSON-with-Comments), suportado pelas settings do VS Code, pelo tsconfig.json do TypeScript e vários parsers de arquivo de config.

4. Sem undefined, funções ou symbols

// Objeto JavaScript —— aceita valores não serializáveis
const obj = {
  fn: () => 42,         // função
  sym: Symbol('id'),    // Symbol
  val: undefined,       // undefined
};

// JSON.stringify silenciosamente descarta ou converte
JSON.stringify(obj);
// → '{}'   (as três propriedades somem ou viram null)

JSON suporta exatamente seis tipos de valor: string, number, boolean (true/false), null, object e array. Funções, Symbols e undefined não têm representação em JSON. JSON.stringify() silenciosamente descarta propriedades de objeto com esses valores e os converte para null dentro de arrays.

5. Sem NaN ou Infinity

JSON.stringify({ ratio: NaN, limit: Infinity });
// → '{"ratio":null,"limit":null}'
// NaN e Infinity viram null —— silenciosamente!

JSON.parse('{"ratio": NaN}');
// → SyntaxError: Unexpected token 'N'

NaN e Infinity são valores numéricos válidos em JavaScript mas não fazem parte da especificação de número do JSON. JSON.stringify() os converte pra null na saída; JSON.parse() os rejeita na entrada. Essa assimetria é uma fonte comum de bugs sutis.

6. Números: sem hex, sem zeros à esquerda, sem +

// ❌ JSON inválido
{ "flags": 0xFF, "code": 007, "delta": +1.5 }

// ✅ JSON válido
{ "flags": 255, "code": 7, "delta": 1.5 }

Números JSON precisam ser decimais, não podem começar com sinal + explícito, e não podem ter zeros à esquerda (exceto o dígito único 0 antes de um ponto decimal). Literais hexadecimais e octais não são JSON válido.

7. Sem strings multilinha

// ❌ JSON inválido —— quebra de linha literal na string
{ "bio": "Line one
Line two" }

// ✅ Use a sequência de escape
{ "bio": "Line one\nLine two" }

8. Keys computadas, keys Symbol e shorthand de método

Mais três features exclusivas do JS que parecem JSON mas não têm equivalente:

// ❌ Nomes de propriedade computados —— avaliados, não literais
const k = "id";
const obj = { [k]: 1, [`user_${k}`]: 1 };
// JSON não tem expressões; a key precisa ser uma string literal entre aspas duplas.

// ❌ Keys Symbol —— silenciosamente descartadas pelo JSON.stringify
const tag = Symbol('tag');
JSON.stringify({ [tag]: 'admin' });  // → '{}'

// ❌ Shorthand de método —— funções são descartadas/omitidas
const obj = { greet() { return 'hi'; } };
JSON.stringify(obj);  // → '{}'

Se você precisa de uma dessas, serialize uma projeção em forma de JSON do seu objeto —— JSON.stringify() só produz keys string e os seis tipos de valor JSON.

Uma cheatsheet rápida de conversão

Object literal do JavaScriptEquivalente JSON válido
{ name: "Ada" }{"name":"Ada"}
{ 'name': 'Ada' }{"name":"Ada"}
{ a: 1, }{"a":1}
{ val: undefined }{} (propriedade descartada)
{ n: NaN }{"n":null}
{ n: Infinity }{"n":null}
{ fn: () => 1 }{} (propriedade descartada)
0xFF255

O jeito mais seguro de converter um objeto JS pra JSON

Nunca tente converter um objeto JavaScript pra JSON editando aspas à mão. Use JSON.stringify() —— ele lida com cada caso de borda corretamente:

const obj = { name: 'Ada', score: 98, active: true };

// Compacto
JSON.stringify(obj);
// → '{"name":"Ada","score":98,"active":true}'

// Pretty-print com indent de 2 espaços
JSON.stringify(obj, null, 2);
// → '{
  "name": "Ada",
  "score": 98,
  "active": true
}'

O segundo argumento do JSON.stringify() é um replacer —— você pode passar um array de nomes de key pra incluir só essas propriedades, ou uma função pra transformar valores:

// Incluir só keys específicas
JSON.stringify(obj, ['name', 'score'], 2);
// → '{
  "name": "Ada",
  "score": 98
}'

// Replacer customizado —— converter undefined em null
JSON.stringify({ a: 1, b: undefined }, (key, value) =>
  value === undefined ? null : value
);
// → '{"a":1,"b":null}'

Quando você recebe um object literal JS como string

Às vezes você recebe dado que parece JSON mas na verdade é um object literal do JavaScript —— talvez de um arquivo de log, uma ferramenta de debug, ou uma API que não seguia a spec. Nesse caso JSON.parse() vai falhar e você tem duas opções:

  • Use um parser de reparo —— converte aspas simples em duplas, remove vírgulas no final, coloca aspas em keys nuas e lida com todas as outras diferenças automaticamente. É a abordagem mais segura pra input não confiável.
  • Use eval() ou Function() —— tecnicamente funciona pra JavaScript válido, mas é um risco de segurança sério se a fonte não é totalmente confiável. Nunca faça isso com input fornecido pelo usuário.

Perguntas frequentes

JSON suporta aspas simples?

Não. A gramática do JSON (RFC 8259) define exatamente um delimitador de string —— aspas duplas. Tanto keys quanto valores precisam usar aspas duplas; aspas simples lançam um SyntaxError.

Qual a diferença entre JSON e um objeto JavaScript?

JSON é um formato de texto estrito; um object literal do JavaScript é código permissivo. JS permite aspas simples, keys sem aspas, vírgulas no final, comentários, undefined, NaN, funções e números hex —— nada disso é JSON válido. Veja a cheatsheet completa acima e o primer em O que é JSON?

Como converto um objeto JavaScript pra JSON?

Use JSON.stringify() —— nunca edite aspas à mão. Ele lida com todo caso de borda, descarta valores não serializáveis e faz escape de strings corretamente.

Por que não posso usar eval() pra parsear um object literal JS?

eval() executa código arbitrário, então é um risco de segurança sério em input não confiável. Use um parser de reparo (ou JSON Fix) pra converter um object literal JS em JSON válido com segurança.

Conserte aspas simples na hora

Se você tem um object literal JavaScript que precisa converter pra JSON válido agora, JSON Fix faz a conversão automaticamente. Ele converte aspas simples em duplas, coloca aspas em keys nuas, remove vírgulas no final e conserta todas as outras diferenças listadas acima —— no seu navegador, sem dado enviado pra qualquer servidor.