Processamento JSON em TypeScript: das operações básicas à tipagem avançada
JSON (JavaScript Object Notation) continua sendo o principal formato de troca de dados no desenvolvimento web. O TypeScript adiciona ao trabalho com JSON um poderoso sistema de tipos, que permite evitar muitos erros na fase de compilação. Neste artigo, abordaremos todos os aspectos do processamento JSON em TypeScript: desde o parsing simples até a criação de validadores estritamente tipados.
Parsing e serialização básicos
Vamos começar com as operações fundamentais. Os métodos nativos JSON.parse() e JSON.stringify() funcionam em TypeScript da mesma forma que em JavaScript, mas com diferenças importantes na tipagem.
// Parsing simples — o resultado será anyconst data: any = JSON.parse('{"name": "Alice", "age": 30}');
// Melhor especificar o tipo imediatamenteinterface User { name: string; age: number;}
const user: User = JSON.parse('{"name": "Alice", "age": 30}') as User;console.log(user.name); // AliceÉ importante entender: as User é uma afirmação de tipo (type assertion), não uma verificação. Se o JSON contiver dados inválidos, o TypeScript não o alertará sobre o erro. Para um trabalho seguro, é necessária validação.
Parsing seguro com Generics
Vamos criar uma função universal para parsing seguro de JSON com verificação de estrutura:
function safeParse<T>(json: string, validator: (data: unknown) => data is T): T | null { try { const parsed: unknown = JSON.parse(json); if (validator(parsed)) { return parsed; } return null; } catch { return null; }}
// Definindo o tipo e a função-validadorainterface Product { id: number; title: string; price: number;}
function isProduct(data: unknown): data is Product { if (typeof data !== 'object' || data === null) return false; const obj = data as Record<string, unknown>; return ( typeof obj.id === 'number' && typeof obj.title === 'string' && typeof obj.price === 'number' );}
const jsonString = '{"id": 1, "title": "Book", "price": 19.99}';const product = safeParse<Product>(jsonString, isProduct);if (product) { console.log(`Produto: ${product.title}, preço: ${product.price}`);} else { console.log('Formato JSON inválido');}Trabalhando com estruturas aninhadas e arrays
Dados JSON reais frequentemente contêm objetos aninhados e arrays. Vejamos um exemplo com tipagem de estrutura complexa:
interface Order { id: string; customer: { name: string; email: string; }; items: Array<{ productId: number; quantity: number; }>; total: number;}
// Parseamos e verificamos a estrutura imediatamentefunction parseOrder(json: string): Order { const raw = JSON.parse(json); // Verificação simples if (!raw.id || !raw.customer || !Array.isArray(raw.items)) { throw new Error('Estrutura de pedido inválida'); } return raw as Order;}
const orderJson = `{ "id": "ORD-001", "customer": {"name": "Bob", "email": "bob@example.com"}, "items": [{"productId": 42, "quantity": 2}], "total": 59.98}`;
try { const order = parseOrder(orderJson); console.log(`Pedido ${order.id} no valor de ${order.total}`);} catch (e) { console.error('Erro de parsing:', e.message);}Serialização com conversores personalizados
Às vezes, é necessário controlar como os objetos são convertidos em JSON. O TypeScript permite criar serializadores personalizados:
interface Config { host: string; port: number; timeout: number; // em milissegundos}
function serializeConfig(config: Config): string { return JSON.stringify({ host: config.host, port: config.port, timeout: config.timeout / 1000 // converte para segundos }, null, 2); // formatação com indentação}
const myConfig: Config = { host: 'localhost' Também na biblioteca
Trabalhando com S3 e armazenamentos em nuvem em C# (.NET): AWS SDK e MinIO
Rate Limiting em Kotlin: bibliotecas e implementação
charm/bubbletea para Go: guia completo com exemplos
Biblioteca Padrão PHP: visão geral completa de funções e classes
Criterion para Rust: guia completo com exemplos práticos