JSON na prática
Esta aula explora o JSON na prática, desde sua definição até o uso com APIs, passando pelos métodos JSON.parse e JSON.stringify, além de pegadinhas comuns. O aluno aprenderá a manipular dados JSON em JavaScript com exemplos reais e exercícios.
JSON (JavaScript Object Notation) é um formato leve de troca de dados, fácil de ler e escrever para humanos e fácil de interpretar e gerar para máquinas. Embora seja derivado da sintaxe de objetos JavaScript, é independente de linguagem e amplamente utilizado em APIs web, arquivos de configuração e armazenamento de dados.
Nesta aula, vamos focar no uso prático de JSON em JavaScript: como converter entre objetos JavaScript e strings JSON, evitar erros comuns e consumir dados de APIs reais.
O que é JSON
JSON é uma string que representa dados estruturados no formato de pares chave-valor e listas ordenadas. Ele suporta tipos primitivos: string, número, booleano, null, objeto e array. Diferente de objetos JavaScript, as chaves devem estar entre aspas duplas, e não são permitidos comentários ou funções.
Exemplo de JSON válido:
{
"nome": "Ana",
"idade": 28,
"ativo": true,
"habilidades": ["JS", "Python"],
"endereco": null
}Observe que as strings usam aspas duplas, não simples. Isso é obrigatório no JSON. Além disso, números não têm aspas, booleanos são escritos em minúsculo e null é a palavra reservada.
JSON.parse e JSON.stringify
Para trabalhar com JSON em JavaScript, usamos dois métodos estáticos do objeto global JSON:
JSON.parse(): converte uma string JSON em um valor JavaScript (objeto, array, etc.).JSON.stringify(): converte um valor JavaScript em uma string JSON.
Exemplo prático:
// String JSON
const jsonString = '{"nome":"João","idade":30}';
// Converter para objeto
const pessoa = JSON.parse(jsonString);
console.log(pessoa.nome); // "João"
// Voltar para string
const novaString = JSON.stringify(pessoa);
console.log(novaString); // '{"nome":"João","idade":30}'
JSON.parse também aceita um segundo parâmetro opcional, um reviver (função de transformação) que pode modificar os valores durante a conversão. Já JSON.stringify aceita um replacer (função ou array para filtrar chaves) e um space (número ou string para formatação com indentação).
// Usando reviver para converter datas
const jsonComData = '{"data":"2023-12-25T10:00:00Z"}';
const obj = JSON.parse(jsonComData, (key, value) => {
if (key === 'data') return new Date(value);
return value;
});
console.log(obj.data instanceof Date); // true
// Usando replacer e space
const filtrado = JSON.stringify(pessoa, ['nome'], 2);
console.log(filtrado);
// '{
// "nome": "João"
// }'
Pegadinhas
Ao trabalhar com JSON, alguns erros são comuns:
- Aspas simples ou sem aspas: JSON exige aspas duplas nas chaves e strings. Usar aspas simples ou omitir aspas causa erro de sintaxe.
- Vírgula sobrando: JSON não permite vírgula após o último par ou elemento. Exemplo inválido:
{"a":1,}. - Tipos não suportados:
undefined, funções, símbolos, e datas (como objeto) não são suportados.JSON.stringifyignoraundefinede funções, e converte datas para string ISO. - Objetos com referências circulares:
JSON.stringifylança um erro se o objeto tiver referências circulares (ex:obj.self = obj). - Precisão numérica: Números muito grandes ou com muitas casas decimais podem perder precisão. Use strings para números que exijam precisão exata (ex: IDs grandes).
Exemplo de erro de sintaxe:
// Incorreto - aspas simples
const invalido = "{'nome': 'Maria'}";
try {
JSON.parse(invalido);
} catch (e) {
console.log(e.message); // Unexpected token ' in JSON at position 1
}
// Correto
const valido = '{"nome":"Maria"}';
JSON.parse(valido); // funciona
Outra pegadinha: JSON.stringify pode produzir saídas inesperadas para certos valores:
console.log(JSON.stringify(undefined)); // undefined (não retorna string)
console.log(JSON.stringify([undefined])); // '[null]'
console.log(JSON.stringify({a: undefined})); // '{}'
Uso com APIs
Na prática, o JSON é o formato mais comum para comunicação com APIs REST. Usamos fetch para fazer requisições e processar a resposta como JSON. Exemplo de consumo de uma API pública:
// Buscar dados de usuários
fetch('https://jsonplaceholder.typicode.com/users/1')
.then(response => {
if (!response.ok) throw new Error('Erro na requisição');
return response.json(); // retorna uma Promise que resolve para o objeto
})
.then(usuario => {
console.log(usuario.name); // "Leanne Graham"
console.log(usuario.email); // "Sincere@april.biz"
})
.catch(erro => console.error(erro));
Para enviar dados no corpo de uma requisição POST, usamos JSON.stringify e definimos o cabeçalho Content-Type como application/json:
const novoUsuario = {
name: 'Maria',
email: 'maria@example.com'
};
fetch('https://jsonplaceholder.typicode.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(novoUsuario)
})
.then(res => res.json())
.then(data => console.log('Criado:', data));
Lembre-se de sempre tratar erros: rede, status HTTP não-2xx, e JSON malformado. Use try/catch com async/await para um código mais limpo:
async function buscarUsuario(id) {
try {
const res = await fetch(`https://jsonplaceholder.typicode.com/users/${id}`);
if (!res.ok) throw new Error(`Status: ${res.status}`);
const usuario = await res.json();
return usuario;
} catch (erro) {
console.error('Falha ao buscar usuário:', erro);
return null;
}
}
buscarUsuario(1).then(u => console.log(u?.name));
Boas práticas
- Sempre valide JSON recebido de fontes externas antes de usar.
- Use
JSON.parsecom try/catch para evitar que erros quebrem a aplicação. - Ao criar APIs, retorne JSON com chaves consistentes (ex: snake_case ou camelCase, mas escolha um padrão).
- Evite enviar dados sensíveis em JSON sem criptografia (use HTTPS).
- Para objetos complexos, considere usar bibliotecas de serialização (ex:
superjsonpara datas).
Referências
- MDN: JSON
- MDN: JSON.parse()
- MDN: JSON.stringify()
- Introdução ao JSON (json.org)
- JSONPlaceholder - API fake para testes
- MDN: Usando Fetch
Exercícios
Crie uma string JSON representando um livro com propriedades: título (string), autor (string), ano (número) e gêneros (array de strings). Converta essa string em um objeto JavaScript e exiba o título no console.
✓ Resposta:const jsonLivro = '{"titulo":"O Senhor dos Anéis","autor":"J.R.R. Tolkien","ano":1954,"generos":["Fantasia","Aventura"]}'; const livro = JSON.parse(jsonLivro); console.log(livro.titulo); // "O Senhor dos Anéis"Dado o objeto
const carro = { marca: 'Fiat', modelo: 'Uno', ano: 2020 }, converta-o para uma string JSON formatada com indentação de 4 espaços e exiba no console.✓ Resposta:const carro = { marca: 'Fiat', modelo: 'Uno', ano: 2020 }; const jsonCarro = JSON.stringify(carro, null, 4); console.log(jsonCarro); // Saída: // { // "marca": "Fiat", // "modelo": "Uno", // "ano": 2020 // }Qual será a saída do código abaixo? Explique por que.
const obj = { a: 1, b: undefined, c: function() {} }; console.log(JSON.stringify(obj));✓ Resposta:Saída:
{"a":1}. Oundefinede a função são ignorados porJSON.stringify, pois não são tipos suportados pelo JSON. Apenas a propriedadeacom valor numérico é incluída.Usando a API JSONPlaceholder (https://jsonplaceholder.typicode.com/posts/1), faça uma requisição fetch para obter o post com id 1 e exiba o título e o corpo no console. Trate possíveis erros.
✓ Resposta:fetch('https://jsonplaceholder.typicode.com/posts/1') .then(response => { if (!response.ok) throw new Error('Erro: ' + response.status); return response.json(); }) .then(post => { console.log('Título:', post.title); console.log('Corpo:', post.body); }) .catch(error => console.error('Falha na requisição:', error));Crie uma função que receba um objeto JavaScript e retorne uma string JSON, mas apenas com as propriedades cujo valor seja do tipo string. Use o parâmetro replacer de
JSON.stringify.✓ Resposta:function filtrarStrings(obj) { return JSON.stringify(obj, (key, value) => { if (typeof value === 'string') return value; return undefined; }); } const teste = { nome: 'Ana', idade: 30, cidade: 'SP' }; console.log(filtrarStrings(teste)); // '{"nome":"Ana","cidade":"SP"}'