محتويات الدورة

Flutter / حدود التطبيق غير المتزامنة / الدرس 8

النماذج المحددة النوع وحدود JSON

تحقّق من شكل البيانات الخارجية قبل إنشاء النماذج واحفظ الفرق بين المعيب والغائب والصحيح.

وقت القراءة التقريبي: 5 دقيقةتاريخ مراجعة المحتوى
في هذه الصفحة

أهداف الدرس

  • JSON المفكوك ليس نموذج مجال بعد
  • نمذج المعنى والوحدات
  • افحص الشكل قبل التحويل القسري

JSON المفكوك ليس نموذج مجال بعد

يثبت فك JSON صحة الصياغة وينتج قيما عامة في Dart مثل الخرائط والقوائم والأرقام والنصوص والقيم المنطقية وnull. لكنه لا يثبت أن حقل seats عدد صحيح غير سالب أو أن لكل سجل معرّفا فريدا. عامل الكائن المفكوك كمدخل حدود غير موثوق، حتى لو كانت الخدمة لفريقك. قد تخرق إصدارات الخدمة ومحتويات التخزين المؤقت وبيانات الاختبار التالفة الافتراضات. أنشئ نموذجا محدد النوع بعد فحص الحقول اللازمة فعلا، مع سياسة صريحة للحقول المفقودة والمجهولة.

نمذج المعنى والوحدات

يسهل النموذج الثابت فهم الحالة المقبولة لأن العنصر يستطيع الاعتماد على ثوابته. استخدم أسماء مثل availableSeats أو priceCents بدلا من value العام حين تهم الوحدة. افصل تمثيل النقل عن تنسيق العرض؛ فالنص الزمني واللحظة المحللة والتاريخ المرئي المترجم تؤدي أدوارا مختلفة. قد يثبت منشئ النموذج شروطا صغيرة، بينما ينسق المستودع العلاقات بين السجلات. ولا تسمح لقيمة افتراضية مريحة بتحويل السعر المفقود إلى صفر إلا إذا نص العقد على ذلك، فالعدد المقنع قد يخفي عيبا خطيرا.

افحص الشكل قبل التحويل القسري

يقبل المقتطف الأول كائنا عاما مفكوكا ويفحص شكله قبل قراءة الحقول المحددة النوع. يرمي المحتوى المعيب FormatException بوصف تشخيصي مستقر. نطاق النموذج ضيق عمدا لهذا التمرين. وقد يعيد التطبيق فشلا منظما لفك الترميز بدلا من الاستثناء، لكن عليه حفظ الحد الذي رفض السجل. تجنب إعادة الحمولة الحساسة كاملة في رسالة الخطأ. ولأن الحقول المعادة نهائية ومتحقق منها، يستطيع العرض استعمالها دون تحويلات dynamic متكررة وأمل ببقاء النقل متسقا.

dart مقتطف توضيحي من Dart أو Flutter؛ يتطلب بيئة SDK المبيّنة.
class Workshop {
  const Workshop(this.id, this.seats);
  final String id;
  final int seats;
  factory Workshop.fromJson(Object? raw) {
    if (raw is! Map<String, dynamic>) throw const FormatException('Expected object');
    final id = raw['id'];
    final seats = raw['seats'];
    if (id is! String || id.isEmpty) throw const FormatException('Invalid id');
    if (seats is! int || seats < 0) throw const FormatException('Invalid seats');
    return Workshop(id, seats);
  }
}
الناتج المتوقع
A valid object becomes Workshop; malformed fields throw the stated FormatException.

تثبت الفحوص الأنواع وشرط المقاعد غير السالبة قبل الإنشاء. يفترض المقتطف فك مفاتيح خريطة JSON كنصوص.

اختبر القيم القريبة من الصحة

يوضح المقتطف الثاني سجلا صحيحا ونصا رقميا غير مقبول. لا يُقبل النص 3 كالعدد الصحيح 3، لأن التحويل لم يكن ضمن العقد المختار. إذا سمحت خدمة خارجية بالشكلين صراحة فطبّعهما عند حد موثق واحد وارفض القيم الغامضة. لا توزع int.parse في العناصر، حيث يصبح الفشل استثناء عرض. وميّز الحقل المفقود من حقل اختياري يسمح صراحة بالقيمة null. يمكن لمخطط النقل التطور دون جعل كل حقل اختياريا أو إسقاط ثوابت التطبيق بصمت.

dart مقتطف توضيحي من Dart أو Flutter؛ يتطلب بيئة SDK المبيّنة.
void checkBoundary() {
  final valid = Workshop.fromJson({'id': 'w-7', 'seats': 3});
  print('${valid.id}:${valid.seats}');
  try {
    Workshop.fromJson({'id': 'w-8', 'seats': '3'});
  } on FormatException catch (error) {
    print(error.message);
  }
}
الناتج المتوقع
w-7:3
Invalid seats

تعتمد هذه الدالة على Workshop في المقتطف السابق. ليست مستقلة، ونتائجها أمثلة مستنتجة.

اختر سياسة فشل المجموعة

إذا كان سجل واحد في الرد معيبا فقرّر هل يفشل الرد كله أم تظهر السجلات الصحيحة مع حالة بيانات جزئية صريحة. قد يجعل تخطي السجلات المعيبة بصمت المجاميع والصفحات مضللة. قد يفيد العرض الجزئي في كتالوج مستقل الصفوف، بينما يفسد حذف سجل واحد ملخصا ماليا. وتنتمي المعرّفات المكررة إلى حدود المجموعة، فقد يتعارض نموذجان صحيحان منفردان عند جمعهما. افحص الاتساق قبل تسليم القائمة للعناصر ذات المفاتيح أو دمجها بالتخزين المؤقت.

اجعل فك الترميز والعرض قابلين للاختبار باستقلال

استخدم عينات مصطنعة صغيرة للحالات الصحيحة والمفقودة وnull والنوع الخاطئ والخروج عن النطاق والتكرار. أكّد فئة الفشل على مستوى التطبيق بدلا من الاعتماد على استثناء تحويل عارض. ثم اختبر العرض بنماذج صحيحة مسبقا كي لا يختلط الخلل المرئي بتحليل النقل. قد يقلل توليد الشيفرة تكرار الربط، لكن التحويلات المولدة لا تقرر ثوابت العمل أو سياسة التوافق. راجع السلوك المولد واحفظ مخطط المصدر وإعداد المولد وإصدارات الاعتماديات قابلة لإعادة الإنتاج ضمن سير المشروع.

الأخطاء الشائعة وإصلاحها

يرمي العنصر استثناء تحويل لحقل seats

لماذا يحدث؟
وصلت قيم النقل إلى العرض دون تحقق عند الحدود.
كيف تصلحه؟
فك الترميز وتحقق داخل نموذج قبل العرض.
كيف تتجنب تكراره؟
اختبر عينات النوع الخاطئ مستقلة عن العناصر.

تتحول البيانات المفقودة إلى صفر مقنع

لماذا يحدث؟
ألغت قيمة افتراضية فرقا مهما بين الغياب والصفر.
كيف تصلحه؟
ارفض الغياب أو نمذجه صراحة بحسب المخطط.
كيف تتجنب تكراره؟
وثّق القيم الافتراضية كقرارات مجال.

تنتج سجلات صحيحة منفردة مفاتيح صفوف مكررة

لماذا يحدث؟
لم تُفحص الهوية على مستوى المجموعة.
كيف تصلحه؟
تحقق من التفرد قبل نشر المجموعة.
كيف تتجنب تكراره؟
أدرج المعرّفات المتعارضة في اختبارات فك الترميز.

اختبر فهمك

1. هل يقبل المفكك المعروض seats: 3.0؟

اعرض الحل المشروح

لا، يشترط العقد int بينما هذه القيمة double. إذا سمح عقد الخدمة بقيم عشرية ذات معنى صحيح، فأضف تحويلا موثقا يفحص المحدودية والتكامل والنطاق. لا تعتمد على القطع لأن 3.9 ستصبح 3 بصمت.

2. يحوي الرد تسعة صفوف صحيحة وصفا معيبا. هل التخطي آمن دائما؟

اعرض الحل المشروح

لا. قيّم هل يحفظ الحذف معنى المهمة. قد يقبل كتالوج جزئي إذا وُسم بوضوح، بينما يحتاج مجموع متسق إلى رفض الرد كله. اجعل السياسة ظاهرة للمستدعين واختبرها بدلا من إخفائها في catch.

أهم ما تعلمته

  • JSON المفكوك ليس نموذج مجال بعد
  • اجعل فك الترميز والعرض قابلين للاختبار باستقلال

المراجع الرسمية