TypeScript中的JSON处理:从基本操作到高级类型化
JSON(JavaScript Object Notation)仍然是Web开发中数据交换的主要格式。TypeScript为JSON处理添加了强大的类型系统,可以在编译阶段避免许多错误。在本文中,我们将全面解析TypeScript中JSON处理的各个方面:从简单的解析到创建严格类型化的验证器。
基本解析与序列化
我们从基础操作开始。内置方法JSON.parse()和JSON.stringify()在TypeScript中的工作方式与JavaScript相同,但在类型化方面有重要区别。
// 简单解析——结果类型为anyconst data: any = JSON.parse('{"name": "Alice", "age": 30}');
// 最好直接指定类型interface User { name: string; age: number;}
const user: User = JSON.parse('{"name": "Alice", "age": 30}') as User;console.log(user.name); // Alice需要理解的是:as User是类型断言,而不是类型检查。如果JSON包含无效数据,TypeScript不会提示错误。为了安全操作,需要进行验证。
使用泛型进行安全解析
我们创建一个通用函数,用于安全解析JSON并进行结构验证:
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; }}
// 定义类型和验证器函数interface 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(`商品:${product.title},价格:${product.price}`);} else { console.log('JSON格式无效');}处理嵌套结构和数组
实际的JSON数据通常包含嵌套对象和数组。我们来看一个复杂结构类型化的例子:
interface Order { id: string; customer: { name: string; email: string; }; items: Array<{ productId: number; quantity: number; }>; total: number;}
// 解析并立即检查结构function parseOrder(json: string): Order { const raw = JSON.parse(json); // 简单检查 if (!raw.id || !raw.customer || !Array.isArray(raw.items)) { throw new Error('订单结构无效'); } 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(`订单 ${order.id},金额 ${order.total}`);} catch (e) { console.error('解析错误:', e.message);}使用自定义转换器进行序列化
有时需要控制对象如何转换为JSON。TypeScript允许创建自定义序列化器:
interface Config { host: string; port: number; timeout: number; // 以毫秒为单位}
function serializeConfig(config: Config): string { return JSON.stringify({ host: config.host, port: config.port, timeout: config.timeout / 1000 // 转换为秒