JSONTech

JSON API Best Practices for Developers

Design better JSON APIs with consistent naming, structured responses, proper pagination, error handling, and performance optimizations used by top engineering teams.

فريق JSONTechFebruary 1, 202510 min read

لماذا تصميم واجهة برمجة التطبيقات مهم

واجهة برمجة التطبيقات المصممة بشكل جيد هي الفرق بين تكامل يستغرق بعد الظهر وواحد يستغرق أسبوعًا. يقلل تصميم واجهة برمجة التطبيقات الجيد من تذاكر الدعم، ويجعل الوثائق الخاصة بك أقصر، ويسمح للمستهلكين بالتنبؤ بكيفية عمل الأشياء قبل قراءة الوثائق.

الأنماط في هذا الدليل ليست نظرية — بل مستمدة من واجهات برمجة التطبيقات في Stripe وGitHub وSlack وغيرها من الشركات المعروفة بتجربة المطور الممتازة. دعنا نستعرض كل واحدة.

اتفاقيات التسمية

الأسلوبان السائدان لأسماء خصائص JSON هما camelCase و snake_case. كلاهما مقبول طالما اخترت واحدًا واستخدمته في كل مكان.

الاتفاقيةالمثالالمستخدمونالنظام البيئي
camelCasefirstName, createdAtواجهات برمجة التطبيقات من Google، Azureواجهات أمامية بلغة JavaScript / TypeScript
snake_casefirst_name, created_atStripe، GitHub، Slackواجهات خلفية بلغة Python / Ruby

إرشاد: اختر الاتفاقية التي تتناسب مع النظام البيئي للمستهلكين الأساسيين لديك. إذا كانت واجهة برمجة التطبيقات الخاصة بك تُستخدم في الغالب من قبل واجهات أمامية بلغة JavaScript، فإن camelCase يتجنب الاحتكاك. إذا كانت واجهتك الخلفية بلغة Python أو Ruby وكانت واجهة برمجة التطبيقات B2B، فإن snake_case هو الأسلوب الشائع.

مهما اخترت، كن متسقًا تمامًا. خلط user_name و firstName في نفس الاستجابة يقوض الثقة أسرع من أي شيء آخر تقريبًا.

هيكل الاستجابة المتسق

يجب أن تتبع كل استجابة من واجهة برمجة التطبيقات الخاصة بك غلافًا يمكن التنبؤ به. إليك نمط يعمل لمعظم واجهات برمجة التطبيقات:

استجابة النجاح

{
  "data": {
    "id": "usr_abc123",
    "email": "alice@example.com",
    "name": "Alice Johnson",
    "created_at": "2025-01-15T09:30:00Z"
  },
  "meta": {
    "request_id": "req_7f2a9c"
  }
}

استجابة القائمة

{
  "data": [
    { "id": "usr_abc123", "name": "Alice Johnson" },
    { "id": "usr_def456", "name": "Bob Smith" }
  ],
  "meta": {
    "total": 142,
    "page": 1,
    "per_page": 20,
    "request_id": "req_8b3d1e"
  }
}

استجابة الخطأ

{
  "error": {
    "code": "validation_error",
    "message": "يحتوي جسم الطلب على حقول غير صالحة.",
    "details": [
      {
        "field": "email",
        "message": "يجب أن يكون عنوان بريد إلكتروني صالح."
      },
      {
        "field": "age",
        "message": "يجب أن يكون على الأقل 13."
      }
    ]
  },
  "meta": {
    "request_id": "req_4c8e2a"
  }
}

المبدأ الرئيسي: data موجودة عند النجاح، وerror موجودة عند الفشل، وmeta تظهر في كلا الحالتين لتتبع الطلبات والتصفح. يمكن للمستهلكين كتابة معالج استجابة واحد يتحقق من error أولاً.

جرب بنفسك: ألصق استجابة واجهة برمجة التطبيقات في منسق JSON لفحص الهيكل واكتشاف التناقضات.

أنماط التصفح

تحتاج معظم نقاط نهاية القوائم إلى التصفح. هناك ثلاث طرق شائعة، كل منها له مزايا وعيوب مختلفة:

1. التصفح بالانزياح

أبسط نهج. يحدد العميل رقم الصفحة أو الانزياح:

GET /api/users?page=3&per_page=20

{
  "data": [...],
  "meta": {
    "total": 142,
    "page": 3,
    "per_page": 20,
    "total_pages": 8
  }
}

2. التصفح بالمؤشر

بدلاً من أرقام الصفحات، تعيد الخادم مؤشرًا غير شفاف يشير إلى مجموعة النتائج التالية:

GET /api/users?limit=20&after=cursor_abc123

{
  "data": [...],
  "meta": {
    "has_more": true,
    "next_cursor": "cursor_def456"
  }
}

3. التصفح باستخدام مجموعة المفاتيح

يستخدم قيمة عمود حقيقية (مثل الطابع الزمني أو المعرف) كمؤشر. هذا هو التصفح بالمؤشر بدون عدم الشفافية:

GET /api/users?limit=20&created_after=2025-01-15T09:30:00Z

{
  "data": [...],
  "meta": {
    "has_more": true,
    "next_created_after": "2025-01-16T14:22:00Z"
  }
}

مقارنة التصفح

الجانبالانزياحالمؤشرمجموعة المفاتيح
الانتقال إلى الصفحة Nنعملالا
العدد الإجماليسهل الإدراجمكلفمكلف
الأداء على الجداول الكبيرةيتدهور (OFFSET يمسح الصفوف)ثابتثابت
التعامل مع الإدخالات/الحذفيمكن أن يتخطى أو يكرر العناصرثابتثابت
تعقيد التنفيذمنخفضمتوسطمتوسط
المستخدمونتطبيقات الويب التقليديةStripe، SlackTwitter / X

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

معالجة الأخطاء

تخبر استجابات الأخطاء الجيدة المستهلك ما الخطأ، أين، ويفضل كيف يمكن إصلاحه. إليك الهيكل الذي نوصي به:

{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "لقد تجاوزت حد معدل 100 طلب في الدقيقة.",
    "details": [],
    "doc_url": "https://docs.example.com/errors/rate-limit"
  }
}

الـ code هو سلسلة قابلة للقراءة الآلية (ليست رمز حالة HTTP — ذلك يذهب في الاستجابة الفعلية لـ HTTP). الـ message قابل للقراءة البشرية. يوفر مصفوفة details أخطاء على مستوى الحقول لفشل التحقق. وdoc_url يربط بالوثائق حول الخطأ.

رموز الأخطاء الشائعة وتخطيطاتها إلى حالات HTTP:

حالة HTTPرمز الخطأمتى تستخدم
400validation_errorيفشل جسم الطلب في التحقق من المخطط
401unauthorizedالمصادقة مفقودة أو غير صالحة
403forbiddenتم المصادقة ولكن تفتقر إلى الإذن
404not_foundالمورد غير موجود
409conflictمورد مكرر أو حالة تعارض
422unprocessable_entityJSON صالح ولكن غير صحيح دلاليًا
429rate_limit_exceededعدد كبير جدًا من الطلبات
500internal_errorفشل غير متوقع في الخادم

أنواع البيانات والتنسيق

الحصول على أنواع البيانات بشكل صحيح يمنع فئة كاملة من أخطاء التكامل:

التواريخ والأوقات

استخدم دائمًا تنسيق ISO 8601 مع معلومات المنطقة الزمنية:

{
  "created_at": "2025-01-15T09:30:00Z",
  "expires_at": "2025-02-15T23:59:59+05:30"
}

لا تستخدم أوقات Unix في أجسام الاستجابة — فهي ليست قابلة للقراءة البشرية وتخلق غموضًا في المنطقة الزمنية. إذا كنت بحاجة إلى أوقات Unix (مثلًا، لمطالبات JWT)، وثق ذلك بوضوح.

الأعداد الكبيرة

يفقد نوع Number في JavaScript الدقة بعد 2^53 - 1 (9,007,199,254,740,991). إذا كانت معرفاتك أو قيمك النقدية تتجاوز ذلك، استخدم السلاسل:

{
  "id": "9223372036854775807",
  "amount": "99.99",
  "currency": "USD"
}

تستخدم Stripe وTwitter وDiscord جميعها معرفات السلاسل لهذا السبب بالضبط.

القيمة الفارغة مقابل المفقودة

حدد اتفاقية واضحة ووثقها:

  • null — الحقل موجود ولكن ليس له قيمة (مثلًا، لم يقم المستخدم بتعيين سيرة ذاتية بعد).
  • المفتاح المفقود — الحقل غير ذي صلة بهذه المورد أو لم يُطلب (مثلًا، في استجابة جزئية).

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

القيم المنطقية

استخدم القيم المنطقية الحقيقية في JSON، وليس السلاسل أو الأعداد:

// جيد
{ "is_active": true }

// سيء
{ "is_active": "true" }
{ "is_active": 1 }

استراتيجيات الإصدار

تتطور واجهات برمجة التطبيقات. تحتاج إلى استراتيجية لإجراء تغييرات دون كسر المستهلكين الحاليين. الطرق الثلاث الرئيسية:

  • إصدار URL: /v1/users, /v2/users. الأكثر شيوعًا والأكثر وضوحًا. تستخدمه Stripe وGitHub وTwilio. سهل الفهم، سهل التوجيه، ولكن يمكن أن يؤدي إلى تكرار الشيفرة.
  • إصدار الرأس: Accept: application/vnd.api+json;version=2. عناوين URL أنظف ولكن أقل قابلية للاكتشاف. تستخدمه GitHub (كبديل) وAzure.
  • معامل الاستعلام: /users?version=2. بسيط ولكنه يلوث سلسلة الاستعلام. أقل شيوعًا في الممارسة.

إرشاد: إصدار URL هو الافتراضي العملي. إنه صريح، قابل للتخزين المؤقت، ويعمل مع كل عميل HTTP. انحرف فقط إذا كان لديك سبب تقني محدد.

الضغط

JSON هو نص ويضغط بشكل استثنائي جيد. دائمًا ما قم بتمكين الضغط لاستجابات واجهة برمجة التطبيقات:

الخوارزميةنسبة الضغطالسرعةدعم المتصفح
gzipجيد (70–80% تقليل)سريععالمي
Brotli (br)أفضل (75–85% تقليل)أبطأ قليلاً في الضغطجميع المتصفحات الحديثة

بالنسبة لاستجابة JSON نموذجية بحجم 50 كيلوبايت، يقلل gzip الحجم إلى حوالي 10–15 كيلوبايت، وBrotli إلى حوالي 8–12 كيلوبايت. يجب على الخادم احترام رأس Accept-Encoding واختيار وفقًا لذلك. تتعامل معظم الوكلاء العكسية (Nginx، Cloudflare) مع هذا تلقائيًا.

نصائح الأداء

الاستجابات الجزئية (اختيار الحقول)

دع المستهلكين يطلبون فقط الحقول التي يحتاجونها. هذا يقلل من حجم الحمولة وحمل قاعدة البيانات:

GET /api/users?fields=id,name,email

{
  "data": [
    { "id": "usr_abc123", "name": "Alice", "email": "alice@example.com" }
  ]
}

تسمي واجهات برمجة التطبيقات من Google هذا "استجابات جزئية" وتدعمه عبر جميع نقاط النهاية. إنه ذو قيمة خاصة للعملاء على الأجهزة المحمولة في الاتصالات البطيئة.

مجموعات الحقول النادرة

لواجهات برمجة التطبيقات التي تعيد الموارد ذات الصلة، دع المستهلكين يتحكمون في الحقول المضمنة لكل نوع مورد:

GET /api/articles?include=author&fields[article]=title,body&fields[author]=name

هذا نمط من مواصفة JSON:API. إنه يقضي على مشكلة الاستعلام N+1 على العميل مع الحفاظ على الحمولة في الحد الأدنى.

ETags والطلبات الشرطية

أعد ETag في رأس الاستجابات. يمكن للعملاء إرسال If-None-Match في الطلبات اللاحقة، وتعيد 304 Not Modified (جسم فارغ) إذا لم يتغير شيء. هذا يوفر النطاق الترددي ووقت المعالجة للموارد التي لا تتغير غالبًا.

قائمة التحقق الملخصة

قبل شحن واجهة برمجة التطبيقات الخاصة بك، مرر عبر هذه القائمة:

  • اتفاقية تسمية متسقة (camelCase أو snake_case) عبر جميع نقاط النهاية.
  • غلاف استجابة يمكن التنبؤ به مع data وerror وmeta.
  • التصفح على جميع نقاط نهاية القوائم مع حدود موثقة.
  • استجابات خطأ منظمة مع رموز قابلة للقراءة الآلية، ورسائل، وتفاصيل على مستوى الحقول.
  • تواريخ ISO 8601، معرفات السلاسل للأعداد الكبيرة، قيم منطقية حقيقية.
  • استراتيجية إصدار واجهة برمجة التطبيقات موثقة ومفروضة.
  • تمكين ضغط gzip أو Brotli.
  • اختيار الحقول أو مجموعات الحقول النادرة للمستهلكين الحساسين للأداء.

جرب بنفسك: قم بتنسيق والتحقق من استجابات واجهة برمجة التطبيقات الخاصة بك باستخدام منسق JSON للتأكد من أنها تتبع هيكلًا نظيفًا ومتسقًا.

أدوات ذات صلة