TypeScript 中处理 JSON 的入门指南
JSON(JavaScript 对象表示法)仍然是客户端与服务器之间数据交换最流行的格式之一。在作为 JavaScript 严格类型化超集的 TypeScript 中,处理 JSON 需要特别关注数据类型。本文将深入探讨如何在 TypeScript 中正确解析和序列化 JSON,避免典型错误,并充分利用静态类型化的优势。
TypeScript 提供了所有用于处理 JSON 的内置 JavaScript 方法,但为其添加了强大的类型系统。这允许您创建更可靠、更可预测的代码。我们将介绍基本操作和高级技术,包括自定义验证器函数和使用泛型。
JSON 解析基础:JSON.parse()
JSON.parse() 方法将 JSON 字符串转换为 JavaScript 对象。在 TypeScript 中,正确地对结果进行类型化非常重要,以便编译器能够验证对对象属性访问的正确性。
基本语法与类型化
让我们看一个简单的例子:
const jsonString = '{"name": "Anna", "age": 30, "city": "Moscow"}';const user = JSON.parse(jsonString);console.log(user.name); // Anna问题在于 TypeScript 不知道 user 对象的结构。该变量的类型是 any,这使我们失去了类型化的所有优势。正确的解决方案是显式指定类型:
interface User { name: string; age: number; city: string;}
const jsonString = '{"name": "Anna", "age": 30, "city": "Moscow"}';const user: User = JSON.parse(jsonString); // 错误!// 类型 'any' 不能赋值给类型 'User'。TypeScript 会抛出错误,因为 JSON.parse() 返回 any,而我们正尝试将其赋值给一个类型化变量。请使用类型断言:
const user = JSON.parse(jsonString) as User;console.log(user.name.toUpperCase()); // ANNA带类型检查的安全解析
as 类型断言是一个快速的解决方案,但它不能保证数据实际符合预期的结构。对于生产代码,建议创建验证器函数:
function parseUser(data: string): User | null { try { const parsed = JSON.parse(data); if (typeof parsed === 'object' && parsed !== null && typeof parsed.name === 'string' && typeof parsed.age === 'number' && typeof parsed.city === 'string') { return parsed as User; } return null; } catch { return null; }}
const user = parseUser('{"name": "Ivan", "age": 25, "city": "SPb"}');if (user) { console.log(`用户:${user.name},年龄:${user.age}`);}这种方法可以在服务器返回不正确数据时防止运行时错误。
序列化:JSON.stringify()
JSON.stringify() 方法将 JavaScript 对象转换为 JSON 字符串。在 TypeScript 中,此方法的工作方式与 JavaScript 相同,但具有类型意识。
简单序列化
const user: User = { name: 'Maria', age: 28, city: 'Kazan'};
const jsonString = JSON.stringify(user);console.log(jsonString); // {"name":"Maria","age":28,"city":"Kazan"}格式化参数
对于可读性输出,请使用 replacer 和 space 参数:
const user = { name: 'Alexey', age: 35, city: 'Novosibirsk', password: 'secret123'};
// 排除密码字段const jsonString = JSON.stringify(user, ['name', 'age', 'city'], 2);console.log(jsonString);/* 输出:{ "name": "Alexey", "age": 35, "city": "Novosibirsk"}*/