Introdução: JSON e TypeScript — a dupla ideal para trabalhar com dados
JSON (JavaScript Object Notation) é um formato leve de troca de dados que se tornou o padrão de facto para comunicação entre cliente e servidor, bem como para armazenar configurações e transmitir informações estruturadas. TypeScript, sendo um superconjunto fortemente tipado do JavaScript, oferece ferramentas poderosas para trabalhar com JSON de forma segura e previsível. Neste artigo, vamos abordar na prática como fazer o parsing (converter uma string JSON em objeto) e serializar (converter um objeto em string JSON) dados em TypeScript, evitando erros comuns e aproveitando os recursos do sistema de tipos.
Fundamentos: JSON.parse() e JSON.stringify() em TypeScript
TypeScript herda completamente os métodos nativos do JavaScript para trabalhar com JSON: JSON.parse() e JSON.stringify(). No entanto, usá-los em um ambiente fortemente tipado requer uma abordagem especial.
JSON.parse() — da string para o objeto
O método JSON.parse() recebe uma string JSON e retorna um objeto. Em TypeScript, o resultado padrão tem o tipo any, o que nos priva de todas as vantagens da tipagem. Vejamos um exemplo:
const jsonString = '{"name": "TypeScript", "version": 5.3}';const parsed: any = JSON.parse(jsonString);console.log(parsed.name); // Funciona, mas sem autocompletar e verificação de tiposPara obter um resultado tipado, use type assertion (afirmação de tipo):
interface Language { name: string; version: number;}
const jsonString = '{"name": "TypeScript", "version": 5.3}';const parsed = JSON.parse(jsonString) as Language;console.log(parsed.name.toUpperCase()); // Autocompletar funciona!JSON.stringify() — do objeto para a string
JSON.stringify() serializa um objeto em uma string JSON. TypeScript verifica se o objeto passado é válido para serialização (não contém funções, undefined, Symbol, etc.).
interface User { id: number; name: string; isActive: boolean;}
const user: User = { id: 1, name: "Alice", isActive: true };const jsonString = JSON.stringify(user);console.log(jsonString); // '{"id":1,"name":"Alice","isActive":true}'Técnicas avançadas: tipagem e tratamento de erros
Na prática, trabalhar com JSON raramente é perfeito. Os dados podem chegar do servidor em um formato inesperado, conter campos extras ou faltar campos obrigatórios. Vejamos como TypeScript ajuda a lidar com esses problemas.
Criando uma função genérica para parsing seguro
Vamos escrever uma função universal que recebe uma string JSON e retorna um resultado tipado com tratamento de erros:
function safeParse<T>(json: string): T | null { try { return JSON.parse(json) as T; } catch (error) { console.error("Erro ao fazer parsing do JSON:", error); return null; }}
// Usointerface Product { id: number; title: string; price: number;}
const rawData = '{"id": 101, "title": "Laptop", "price": 999.99}';const product = safeParse<Product>(rawData);if (product) { console.log(product.title); // "Laptop"}Validação de dados com guards de tipo personalizados
Mesmo após usar type assertion as T, TypeScript não verifica se os dados realmente correspondem à interface. Para validação em tempo de execução, use type guards:
function isProduct(obj: any): obj is Product { return ( typeof obj === 'object' && obj !== null && typeof obj.id === 'number' && typeof obj.title === 'string' && typeof obj.price === 'number' );}
const rawData = '{"id": "abc", "title": "Phone", "price": 599}';const parsed = JSON.parse(rawData);if (isProd