معالجة JSON في TypeScript: من التحليل الأساسي إلى التصنيف الصارم
TypeScript، كونه طبقة فوق JavaScript، يرث جميع الطرق المضمنة للعمل مع JSON، ولكنه يضيف إليها نظام أنواع قوي. ومع ذلك، فإن JSON.parse() القياسي يُرجع النوع any، مما يلغي جميع مزايا التصنيف الثابت. في هذه المقالة، سنشرح كيفية معالجة JSON بأمان وفعالية في TypeScript، باستخدام كل من الإمكانيات الأصلية والمكتبات المتخصصة.
مشكلة JSON.parse القياسي
لننظر في سيناريو نموذجي:
const jsonString = '{"name":"Alice","age":30}';const user: any = JSON.parse(jsonString); // نوع anyconsole.log(user.name.toUpperCase()); // خطأ أثناء التنفيذ إذا كان name غير موجودلن يحذرك TypeScript إذا كان هيكل JSON لا يتطابق مع المتوقع. الحل هو استخدام تأكيد النوع (type assertion) أو الأفضل - التحقق أثناء التنفيذ.
تأكيد النوع الأساسي (Type Assertion)
أبسط طريقة هي تحديد نوع النتيجة صراحة:
interface User { id: number; name: string; email?: string;}
const raw = '{"id":1,"name":"Bob"}';const user = JSON.parse(raw) as User;console.log(user.name); // TypeScript يعرف أنه stringالعيب: إذا جاء JSON بحقول أخرى، سيحدث الخطأ فقط في وقت التشغيل. هذا غير آمن عند العمل مع واجهات برمجة التطبيقات الخارجية.
الأنواع التكرارية والشرطية لـ JSON
يسمح TypeScript بوصف أي JSON من خلال نوع تكراري:
type JSONValue = | string | number | boolean | null | JSONValue[] | { [key: string]: JSONValue };
function safeParse(json: string): JSONValue | Error { try { return JSON.parse(json) as JSONValue; } catch (e) { return new Error('Invalid JSON'); }}يضمن هذا النهج أن النتيجة ستكون دائمًا هيكل JSON صالحًا، لكنه لا يتحقق من الشكل المحدد.
مكتبة Zod — التحقق من المخططات أثناء التنفيذ
Zod هي المكتبة الأكثر شيوعًا للتحقق التصريحي من البيانات في TypeScript. تتيح وصف مخطط واستخراج النوع منه تلقائيًا.
التثبيت
npm install zodمثال على الاستخدام
import { z } from 'zod';
// وصف المخططconst UserSchema = z.object({ id: z.number().positive(), name: z.string().min(1), email: z.string().email().optional(), role: z.enum(['admin', 'user']).default('user'),});
// استخراج النوع من المخططtype User = z.infer<typeof UserSchema>;
// التحليل الآمنconst result = UserSchema.safeParse(JSON.parse(rawJson));
if (result.success) { // result.data له النوع User console.log(result.data.name);} else { console.error(result.error.format());}يتحقق Zod تلقائيًا من الأنواع، وإلزامية الحقول، والقيم الافتراضية، ويعيد أخطاء مفصلة. هذا هو الخيار المثالي لمعالجة البيانات من REST API أو ملفات التكوين.
مكتبة io-ts — النهج الوظيفي
io-ts مبنية على البرمجة الوظيفية ومكتبة fp-ts. تستخدم تركيب الكوديكات (codecs) لفك/ترميز البيانات.
مثال
import * as t from 'io-ts';import { isRight } from 'fp-ts/lib/Either';
const UserCodec = t.type({ id: t.number, name: t.string, tags: t.array(t.string),});
const decoded = UserCodec.decode(JSON.parse(raw));
if (isRight(decoded)) { // decoded.right — كائن مصنف console.log(decoded.right.name);} else { // decoded.left — أخطاء التحقق console.log(decoded.left);}io-ts أكثر صرامة وصحة رياضية، لكنه يتطلب فهم المفاهيم الوظيفية (Either, pipe).