تنسيقات الطلب والاستجابة
فهم تنسيقات البيانات في واجهات برمجة REST
تحتاج واجهات برمجة REST إلى لغة مشتركة لتبادل البيانات بين العملاء والخوادم. بينما لا تفرض REST نفسها تنسيقاً محدداً، أصبح JSON المعيار الفعلي بسبب بساطته وقابليته للقراءة ودعمه العالمي عبر لغات البرمجة.
JSON: ملك تنسيقات بيانات واجهة البرمجة
JSON (JavaScript Object Notation) خفيف الوزن، قابل للقراءة البشرية، وسهل التحليل. إنه المعيار لواجهات برمجة REST الحديثة.
أساسيات JSON:
{
"id": 123,
"name": "أحمد محمد",
"email": "ahmed@example.com",
"age": 30,
"isActive": true,
"roles": ["user", "editor"],
"address": {
"street": "شارع الرئيسي 123",
"city": "القاهرة",
"zipCode": "11511"
},
"metadata": null
}
أنواع بيانات JSON:
- نص (String): "نص بين علامتي اقتباس مزدوجة"
- رقم (Number): 123, 45.67 (بدون علامات اقتباس)
- منطقي (Boolean): true, false (أحرف صغيرة، بدون علامات اقتباس)
- مصفوفة (Array): ["item1", "item2"]
- كائن (Object): {"key": "value"}
- null: null (يمثل غياب القيمة)
هيكلة استجابات JSON
الهيكل المتسق للاستجابة يجعل واجهتك البرمجية قابلة للتنبؤ وسهلة الاستخدام.
استجابة مورد واحد:
GET /api/users/123
HTTP/1.1 200 OK
Content-Type: application/json
{
"data": {
"id": 123,
"name": "أحمد محمد",
"email": "ahmed@example.com",
"created_at": "2026-01-15T10:30:00Z",
"updated_at": "2026-02-14T14:20:00Z"
}
}
استجابة مجموعة:
GET /api/users?page=1&limit=2
HTTP/1.1 200 OK
Content-Type: application/json
{
"data": [
{
"id": 123,
"name": "أحمد محمد",
"email": "ahmed@example.com"
},
{
"id": 124,
"name": "فاطمة علي",
"email": "fatima@example.com"
}
],
"meta": {
"current_page": 1,
"per_page": 2,
"total": 150,
"total_pages": 75
},
"links": {
"first": "/api/users?page=1",
"prev": null,
"next": "/api/users?page=2",
"last": "/api/users?page=75"
}
}
استجابة خطأ:
POST /api/users
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json
{
"error": {
"code": "VALIDATION_ERROR",
"message": "فشلت بيانات الطلب في التحقق",
"details": [
{
"field": "email",
"message": "البريد الإلكتروني مطلوب",
"code": "REQUIRED_FIELD"
},
{
"field": "age",
"message": "يجب أن يكون العمر 18 على الأقل",
"code": "MIN_VALUE"
}
]
}
}
اصطلاحات تسمية JSON
اختر نمط تسمية والتزم به في جميع أنحاء واجهتك البرمجية.
camelCase (موصى به لواجهات برمجة JavaScript الثقيلة):
{
"userId": 123,
"firstName": "أحمد",
"lastName": "محمد",
"emailAddress": "ahmed@example.com",
"isEmailVerified": true,
"createdAt": "2026-01-15T10:30:00Z"
}
snake_case (شائع في واجهات برمجة Python/Ruby):
{
"user_id": 123,
"first_name": "أحمد",
"last_name": "محمد",
"email_address": "ahmed@example.com",
"is_email_verified": true,
"created_at": "2026-01-15T10:30:00Z"
}
PascalCase (نادر في واجهات برمجة REST):
{
"UserId": 123,
"FirstName": "أحمد",
"LastName": "محمد"
}
تنسيقات التاريخ والوقت
استخدم دائماً تنسيق ISO 8601 للتواريخ والأوقات. إنه واضح ومدعوم عالمياً.
أمثلة ISO 8601:
// التاريخ فقط
"2026-02-14"
// التاريخ والوقت (UTC - موصى به)
"2026-02-14T10:30:00Z"
// التاريخ والوقت مع إزاحة المنطقة الزمنية
"2026-02-14T10:30:00-05:00"
// التاريخ والوقت مع ملي ثانية
"2026-02-14T10:30:00.123Z"
Null مقابل الحقول المفقودة
قرر كيفية التعامل مع البيانات المفقودة وكن متسقاً.
الخيار 1: تضمين قيم Null
{
"id": 123,
"name": "أحمد محمد",
"middleName": null,
"phone": null,
"bio": null
}
المزايا:
✅ صريح بشأن البيانات المفقودة
✅ العميل يعرف أن الحقل موجود
✅ التحقق من المخطط أسهل
العيوب:
❌ حجم استجابة أكبر
❌ أكثر تفصيلاً
الخيار 2: حذف قيم Null
{
"id": 123,
"name": "أحمد محمد"
}
المزايا:
✅ حجم استجابة أصغر
✅ أنظف، أقل فوضى
العيوب:
❌ لا يمكن التمييز بين null وundefined
❌ يجب على العميل التعامل مع المفاتيح المفقودة
رؤوس HTTP: طبقة البيانات الوصفية
توفر الرؤوس معلومات مهمة حول الطلبات والاستجابات دون تشويش الجسم.
رأس Content-Type
يخبر الخادم/العميل بتنسيق البيانات.
// الطلب
POST /api/users
Content-Type: application/json
{"name": "أحمد محمد"}
// الاستجابة
HTTP/1.1 200 OK
Content-Type: application/json
{"id": 123, "name": "أحمد محمد"}
رأس Accept
يخبر العميل الخادم بالتنسيقات التي يمكنه التعامل معها.
// العميل يفضل JSON
GET /api/users
Accept: application/json
// العميل يمكنه التعامل مع تنسيقات متعددة (ترتيب الأفضلية)
GET /api/users
Accept: application/json, application/xml;q=0.9, */*;q=0.8
أنواع المحتوى الشائعة:
| Content-Type | الوصف | الاستخدام |
|---|---|---|
| application/json | بيانات JSON | 99٪ من واجهات برمجة REST |
| application/xml | بيانات XML | الأنظمة القديمة |
| application/x-www-form-urlencoded | بيانات النموذج | نماذج HTML |
| multipart/form-data | تحميلات الملفات | الصور، المستندات |
| text/plain | نص عادي | استجابات بسيطة |
| text/html | مستند HTML | توثيق واجهة البرمجة |
التفاوض على المحتوى
يسمح التفاوض على المحتوى لنفس نقطة النهاية بإرجاع تنسيقات مختلفة بناءً على تفضيل العميل.
التفاوض الذي يقوده الخادم:
// العميل يطلب JSON
GET /api/users/123
Accept: application/json
الاستجابة:
HTTP/1.1 200 OK
Content-Type: application/json
{"id": 123, "name": "أحمد محمد"}
// العميل يطلب XML
GET /api/users/123
Accept: application/xml
الاستجابة:
HTTP/1.1 200 OK
Content-Type: application/xml
<user>
<id>123</id>
<name>أحمد محمد</name>
</user>
التعامل مع التنسيقات غير المدعومة:
GET /api/users/123
Accept: application/pdf
الاستجابة:
HTTP/1.1 406 Not Acceptable
Content-Type: application/json
{
"error": {
"code": "UNSUPPORTED_MEDIA_TYPE",
"message": "لا يمكن للخادم إنتاج استجابة بالتنسيق المطلوب",
"supported_formats": ["application/json", "application/xml"]
}
}
XML: التنسيق البديل
بينما يهيمن JSON، لا تزال بعض أنظمة المؤسسات تستخدم XML.
مثال XML:
<?xml version="1.0" encoding="UTF-8"?>
<user>
<id>123</id>
<name>أحمد محمد</name>
<email>ahmed@example.com</email>
<roles>
<role>user</role>
<role>editor</role>
</roles>
<address>
<street>شارع الرئيسي 123</street>
<city>القاهرة</city>
</address>
</user>
مقارنة JSON مقابل XML:
| الجانب | JSON | XML |
|---|---|---|
| قابلية القراءة | قابل للقراءة جداً | مطول |
| الحجم | أصغر (30-50٪ أقل) | أكبر |
| سرعة التحليل | أسرع | أبطأ |
| أنواع البيانات | أنواع أصلية | كل شيء نص |
| المصفوفات | دعم أصلي | عناصر متكررة |
| التحقق | JSON Schema | XSD، DTD |
| التعليقات | غير مدعوم | مدعوم |
تحميلات الملفات: multipart/form-data
عند تحميل الملفات، استخدم multipart/form-data بدلاً من JSON.
POST /api/users/123/avatar
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary
------WebKitFormBoundary
Content-Disposition: form-data; name="file"; filename="avatar.jpg"
Content-Type: image/jpeg
[بيانات ملف ثنائية]
------WebKitFormBoundary
Content-Disposition: form-data; name="description"
صورة ملف شخصي جديدة
------WebKitFormBoundary--
الاستجابة:
HTTP/1.1 201 Created
Content-Type: application/json
{
"data": {
"id": 456,
"filename": "avatar.jpg",
"size": 51234,
"url": "https://cdn.example.com/avatars/456.jpg",
"uploaded_at": "2026-02-14T10:30:00Z"
}
}
الضغط: تقليل النطاق الترددي
تمكين الضغط لتقليل أحجام الاستجابة بنسبة 60-80٪.
// العميل يقبل الاستجابة المضغوطة
GET /api/users
Accept-Encoding: gzip, deflate, br
// الخادم يرسل استجابة مضغوطة
HTTP/1.1 200 OK
Content-Type: application/json
Content-Encoding: gzip
Content-Length: 1234
[بيانات مضغوطة]
ترميز الأحرف: UTF-8 دائماً
استخدم دائماً ترميز UTF-8 لدعم الأحرف الدولية.
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"name": "José García",
"city": "São Paulo",
"greeting": "你好",
"message": "مرحبا"
}
قائمة التحقق من أفضل الممارسات
- ✅ استخدم JSON كتنسيق أساسي
- ✅ قم دائماً بتعيين رؤوس Content-Type بشكل صحيح
- ✅ استخدم ISO 8601 لجميع التواريخ والأوقات
- ✅ كن متسقاً مع التسمية (camelCase أو snake_case)
- ✅ غلف الاستجابات في كائن "data" للمرونة
- ✅ قم بتضمين البيانات الوصفية للترقيم للمجموعات
- ✅ وفر رسائل خطأ مفصلة مع رموز
- ✅ دعم الضغط (gzip، brotli)
- ✅ استخدم ترميز UTF-8 في كل مكان
- ✅ أرجع 406 لأنواع Accept غير المدعومة
أنشئ هياكل استجابة JSON مناسبة لهذه السيناريوهات:
- إنشاء مستخدم ناجح: معرف المستخدم 789، الاسم "سارة أحمد"، البريد الإلكتروني "sara@example.com"، تم إنشاؤه اليوم في تمام الساعة 10:30 صباحاً UTC
- خطأ التحقق: البريد الإلكتروني غير صالح، كلمة المرور قصيرة جداً (8 أحرف كحد أدنى)
- مجموعة مع الترقيم: 3 منتجات من إجمالي 150، الصفحة 1 من 50، 3 عناصر لكل صفحة
حل عينة للسؤال #1:
HTTP/1.1 201 Created
Content-Type: application/json
Location: /api/users/789
{
"data": {
"id": 789,
"name": "سارة أحمد",
"email": "sara@example.com",
"created_at": "2026-02-14T10:30:00Z"
}
}
النقاط الرئيسية
- JSON هو التنسيق القياسي لواجهات برمجة REST الحديثة
- استخدم دائماً رؤوس Content-Type و Accept بشكل صحيح
- تنسيق ISO 8601 للتواريخ (UTC مع لاحقة Z)
- كن متسقاً مع اصطلاحات التسمية في جميع أنحاء واجهتك البرمجية
- غلف الاستجابات في كائن "data" للمرونة المستقبلية
- قم بتضمين بيانات وصفية مفيدة (الترقيم، الطوابع الزمنية)
- دعم الضغط لتقليل النطاق الترددي
- استخدم ترميز UTF-8 للدعم الدولي