Tutorial de JSON: sintaxe, regras e como trabalhar com JSON em JavaScript e Python

JSON é o formato de troca de dados mais simples e mais usado; com poucas regras curtas e duas funções em cada linguagem, você consegue ler, criar e guardar qualquer dado.

Experimente: Formatador de JSON

Se você trabalha com APIs, aplicativos mobile ou até com o arquivo de configuração de um projeto, mais cedo ou mais tarde vai topar com JSON. JSON é um formato de texto para guardar e transportar dados que as pessoas conseguem ler e que qualquer linguagem de programação processa com facilidade. Este tutorial começa pela definição e pelas regras de sintaxe, passa por um exemplo real, segue para a leitura e a escrita de JSON em JavaScript e Python, com atenção especial a letras acentuadas e outros textos fora do inglês, e termina com os erros mais comuns e como localizá-los com o Formatador de JSON. Todo o código desta página foi executado, e as saídas são reais.

O que é JSON?

JSON é a sigla de JavaScript Object Notation. A sintaxe vem do jeito como os objetos são escritos em JavaScript, mas o formato não depende de nenhuma linguagem: Python, PHP, Java, C#, Go e praticamente todas as outras linguagens têm ferramentas prontas para trabalhar com ele. O JSON é definido pelos padrões RFC 8259 e ECMA-404, os arquivos usam a extensão .json e o tipo de mídia na web é application/json. Usos comuns:

  • APIs web: a maioria dos serviços modernos envia requisições e respostas em JSON.
  • Arquivos de configuração: como o package.json em projetos Node.js ou o composer.json no PHP.
  • Armazenamento de dados: no localStorage do navegador, nas colunas JSON de bancos de dados como PostgreSQL e MySQL e em bancos de dados de documentos.

Regras de sintaxe do JSON

Todo documento JSON é construído a partir de seis tipos de valor, que podem ser aninhados uns dentro dos outros:

TipoExemploDescrição
object{"city": "Lisbon"}Pares de chave e valor entre chaves
array[1, 2, 3]Uma lista ordenada de valores entre colchetes
string"hello"Texto entre aspas duplas
number42, -3.5, 1.2e6Inteiro ou decimal, sem aspas
booleantrue, falseSó em minúsculas
nullnullA ausência de valor

Estas são as regras por trás da maioria dos erros:

  • As chaves são sempre strings entre aspas duplas: {"name": "Ali"} está correto e {name: "Ali"} não está.
  • Só aspas duplas são permitidas; 'Ali' entre aspas simples não é JSON válido.
  • Vírgula no final não é permitida: nenhuma vírgula pode vir depois do último membro de um objeto ou de um array.
  • Não existem comentários: nem // nem /* */.
  • Valores específicos de uma linguagem não são permitidos: undefined, NaN, Infinity, True e None não são JSON válido.
  • Números não podem começar com zero: 012 é inválido. Por isso, números de telefone, códigos postais e identificadores parecidos devem ser escritos como strings, como "0123456789"; assim o zero à esquerda também é preservado.
  • Caracteres especiais dentro de strings são escapados: \" para aspas duplas, \\ para barra invertida, \n para quebra de linha e \uXXXX para qualquer caractere Unicode.
  • Espaços e quebras de linha entre as partes não fazem diferença; é por isso que o JSON pode ser escrito tanto compacto, em uma única linha, quanto bem indentado.

Um exemplo real: o pedido de uma loja virtual

{
  "orderId": 10245,
  "createdAt": "2026-09-17T10:30:00Z",
  "customer": {
    "name": "Maria",
    "phone": "0123456789",
    "city": "Lisbon"
  },
  "items": [
    { "title": "Python for Beginners", "price": 32, "qty": 1 },
    { "title": "Wireless Mouse", "price": 45, "qty": 2 }
  ],
  "paid": true,
  "discountCode": null
}

Este exemplo mostra todos os tipos de valor. customer é um objeto aninhado e items é um array de objetos. Os preços são números, mas o telefone é uma string, para que o zero à esquerda seja mantido. O JSON não tem um tipo "data", então o horário do pedido é uma string no formato padrão ISO 8601. E discountCode usa null para dizer que este pedido não teve cupom de desconto. Para ler o preço do segundo item, você escreve order.items[1].price em JavaScript e order["items"][1]["price"] em Python.

Trabalhando com JSON em JavaScript

O JavaScript tem duas funções nativas que bastam para a maioria das tarefas: JSON.parse transforma texto JSON em objeto, e JSON.stringify transforma um objeto em texto JSON.

Ler JSON com JSON.parse

const text = '{"name": "Maria", "age": 28, "skills": ["JavaScript", "Python"], "active": true}';
const user = JSON.parse(text);

console.log(user.name);       // Maria
console.log(user.skills[0]);  // JavaScript
console.log(user.active);     // true

Criar JSON com JSON.stringify

const product = { title: "Café Guide", price: 32, tags: ["travel", "bestseller"], discount: null };

console.log(JSON.stringify(product));
console.log(JSON.stringify(product, null, 2));

A primeira chamada gera JSON compacto, em uma linha, ideal para enviar pela rede; a segunda, com 2 como terceiro argumento, gera uma saída legível, indentada com dois espaços. O segundo argumento serve para filtrar ou transformar valores e normalmente fica como null. A saída:

{"title":"Café Guide","price":32,"tags":["travel","bestseller"],"discount":null}
{
  "title": "Café Guide",
  "price": 32,
  "tags": [
    "travel",
    "bestseller"
  ],
  "discount": null
}

Letras acentuadas e outros textos não ASCII ficam exatamente como são na saída de JSON.stringify; eles não viram escapes \u.

Buscar JSON de uma API e guardar no localStorage

async function loadProduct() {
  const res = await fetch("https://api.example.com/products/1");
  return await res.json();
}

localStorage.setItem("cart", JSON.stringify({ items: [101, 205] }));
const cart = JSON.parse(localStorage.getItem("cart"));
console.log(cart.items.length); // 2

O método res.json() já faz o parse da resposta e devolve um objeto; não passe o resultado dele de novo para JSON.parse. O localStorage só guarda strings, então o objeto é convertido com JSON.stringify ao ser salvo e com JSON.parse ao ser lido.

Valores que o JSON.stringify altera

const data = { a: undefined, b: () => 1, c: NaN, d: new Date(Date.UTC(2026, 8, 17)) };
console.log(JSON.stringify(data));
// {"c":null,"d":"2026-09-17T00:00:00.000Z"}

Chaves cujo valor é undefined ou uma função são descartadas sem aviso, NaN e Infinity viram null, e uma data vira uma string ISO. Quando você faz o parse do resultado de novo, a data continua sendo string e não volta a ser um Date sozinha.

Tratando erros

try {
  JSON.parse("{'name': 'Ali'}");
} catch (err) {
  console.log(err.name);    // SyntaxError
  console.log(err.message); // Expected property name or '}' in JSON at position 1 (line 1 column 2)
}

Qualquer texto inválido lança um SyntaxError, então processe dados vindos de fora dentro de try...catch. A mensagem acima é a saída do Node.js, igual à do Chrome; o Firefox e o Safari relatam o mesmo erro com outras palavras.

Trabalhando com JSON em Python

Em Python, o módulo padrão json faz todo o trabalho, e não há nada para instalar. Ele tem quatro funções principais: json.loads e json.dumps trabalham com strings, enquanto json.load e json.dump trabalham direto com arquivos; o s das duas primeiras vem de string.

Transformar uma string JSON em dicionário

import json

text = '{"name": "Maria", "age": 28, "skills": ["JavaScript", "Python"], "active": true}'
user = json.loads(text)

print(user["name"])     # Maria
print(type(user))       # <class 'dict'>
print(user["active"])   # True
JSONPythonJavaScript
objectdictObject
arraylistArray
stringstrString
numberint ou floatNumber
true / falseTrue / Falsetrue / false
nullNonenull

Converter dados para JSON e o problema dos textos não ASCII

product = {"title": "Café Guide", "price": 32, "tags": ["travel", "bestseller"], "discount": None}

print(json.dumps(product))
print(json.dumps(product, ensure_ascii=False, indent=2))

A primeira linha da saída pode surpreender:

{"title": "Caf\u00e9 Guide", "price": 32, "tags": ["travel", "bestseller"], "discount": null}

Por padrão, json.dumps escreve todo caractere não ASCII na forma \uXXXX, então é vira \u00e9, e um texto em qualquer outro alfabeto é escapado caractere por caractere do mesmo jeito. Em português, isso atinge cada acento e cada cedilha. Essa saída é válida e qualquer programa a lê corretamente, mas as pessoas não conseguem lê-la, e ela ocupa mais espaço. Com ensure_ascii=False o texto é escrito exatamente como é, e indent=2 organiza a saída igual ao exemplo em JavaScript.

Ler e gravar arquivos JSON

with open("product.json", "w", encoding="utf-8") as f:
    json.dump(product, f, ensure_ascii=False, indent=2)

with open("product.json", encoding="utf-8") as f:
    loaded = json.load(f)

print(loaded["tags"][0])   # travel

Dois pontos importantes: passe ensure_ascii=False também para json.dump, e sempre abra o arquivo com encoding="utf-8". No Windows, se você não especificar a codificação, o Python pode recorrer à codificação padrão do sistema, que não é UTF-8; o resultado é um UnicodeEncodeError ou um arquivo cheio de caracteres embaralhados.

A saída do print não é JSON

print(product)
# {'title': 'Café Guide', 'price': 32, 'tags': ['travel', 'bestseller'], 'discount': None}

Um erro muito comum é colar em algum lugar, como se fosse JSON, a saída do print de um dicionário. Esse texto é a representação própria do Python para os dados: tem aspas simples e None em vez de null, então nenhum parser de JSON vai aceitá-lo. Para criar JSON, use sempre json.dumps.

Tratando erros em Python

try:
    json.loads("{'name': 'Ali'}")
except json.JSONDecodeError as e:
    print(e)  # Expecting property name enclosed in double quotes: line 1 column 2 (char 1)

json.JSONDecodeError é uma subclasse de ValueError, e os atributos lineno, colno e pos indicam a posição do erro. Se você usa a biblioteca requests, response.json() faz a mesma conversão para a resposta de uma API. Uma diferença sutil: por padrão, o Python aceita NaN na entrada e também o escreve na saída, embora esse valor não seja JSON padrão; para impedir isso, passe allow_nan=False para json.dumps.

Erros comuns de JSON e o que as mensagens significam

ErroExemplo inválidoMensagem no JavaScript (Node.js e Chrome)Mensagem no Python
Aspas simples ou chave sem aspas{'name': 'Ali'}Expected property name or '}'Expecting property name enclosed in double quotes
Vírgula sobrando no fim de um objeto{"a": 1,}Expected double-quoted property namePython 3.14: Illegal trailing comma before end of object; Python 3.12: Expecting property name enclosed in double quotes
Vírgula sobrando no fim de um array[1, 2,]Unexpected token ']'Python 3.14: Illegal trailing comma before end of array; Python 3.12: Expecting value
Vírgula faltando, ou comentário depois de um valor{"a": 1 "b": 2}Expected ',' or '}' after property valueExpecting ',' delimiter
Um valor de Python ou de JavaScript{"a": True}Unexpected token 'T'Expecting value
Número com zero à esquerda{"phone": 0123456789}Unexpected numberExpecting ',' delimiter
String não fechada{"a": "x}Unterminated stringUnterminated string starting at
Entrada vaziaTexto vazioUnexpected end of JSON inputExpecting value

As mensagens costumam trazer também a posição, como position 8 ou line 1 column 9, e o problema real muitas vezes está logo antes desse ponto. Se uma mensagem do JavaScript começa com Unexpected token '<', provavelmente você recebeu uma página HTML em vez de JSON, por exemplo uma página de erro 404 ou uma tela de login; o guia sobre o erro Unexpected token explica esse caso passo a passo. Um arquivo salvo com BOM gera o erro Unexpected UTF-8 BOM no Python; abra-o com encoding="utf-8-sig" ou salve-o sem o BOM.

Formatar e validar com o Formatador de JSON

Quando um JSON longo chega em uma única linha, ou você não consegue descobrir por que ele não passa no parse, o Formatador de JSON é o caminho mais rápido. A ferramenta usa o próprio parser de JSON do navegador, e os dados nunca saem do seu navegador, então você pode inspecionar com segurança respostas de API que contêm tokens ou dados de usuários. O passo a passo:

  1. Cole o JSON na caixa JSON de entrada; ele é formatado na hora, e o botão Formatar faz o mesmo.
  2. Escolha a indentação no menu Indentação: 2 espaços, 4 espaços ou Tabulação.
  3. Se o JSON for inválido, uma mensagem começando com JSON inválido: mostra o texto de erro do navegador, que normalmente inclui a posição do problema; use a tabela acima para entender o que ele significa e corrigir.
  4. A aba Árvore mostra os dados como uma árvore recolhível, e Expandir tudo e Recolher tudo abrem ou fecham todos os ramos; muito prático para encontrar uma chave em uma resposta grande.
  5. Para enviar ou guardar os dados de forma compacta, Minificar remove todos os espaços e quebras de linha. Copie o resultado com Copiar.

Quando o seu código precisa de tipos para o JSON que recebe, o JSON para Tipos gera definições em TypeScript, Go ou Python a partir de um exemplo; o guia sobre como tipar respostas de API em TypeScript mostra o passo a passo.

Perguntas Frequentes

O que é JSON e qual a diferença para um objeto JavaScript?

JSON é um formato de texto para guardar e trocar dados cuja sintaxe vem dos objetos JavaScript, mas ele é mais rígido: as chaves precisam estar entre aspas duplas, comentários e vírgulas no final não são permitidos, e valores como undefined e funções não existem nele.

Por que o Python escreve é como \u00e9 no JSON?

Porque o json.dumps usa ensure_ascii=True por padrão e escapa todo caractere não ASCII. A saída é válida, mas, para uma saída legível, passe ensure_ascii=False e grave o arquivo com encoding="utf-8".

Dá para escrever comentários em um arquivo JSON?

Não. O JSON padrão não tem comentários, e JSON.parse e json.loads lançam um erro quando encontram um. Algumas ferramentas, como as configurações do VS Code, aceitam um formato estendido com comentários, mas isso não é JSON padrão.

Qual a diferença entre json.loads e json.load no Python?

json.loads transforma uma string JSON em dados Python, e json.load lê direto de um arquivo aberto. Do mesmo jeito, json.dumps devolve uma string e json.dump grava os dados em um arquivo.
Experimente: Formatador de JSON