JSON: لغة تبادل البيانات
حين يكون العميل برنامجًا لا إنسانًا: بيانات بدل صفحات. ⏱ نحو 30 دقيقة.
- تشرح صيغة
JSONوتقابلها مع أنواعPHP. - تحوّل البيانات بـ
json_encodeوjson_decodeمع الخيارات المناسبة للعربية. - تكتب نقطة
APIترد بـJSONوترويسةContent-Typeصحيحة. - تستقبل
JSONمن جسم الطلب عبرphp://inputوتتعامل معJSONالمعطوب.
١لماذا JSON؟
حتى الآن كان الخادم يرد بصفحات HTML يقرؤها الإنسان. لكن كثيرًا من «العملاء» ليسوا بشرًا: تطبيق جوال (مقرر 251)، أو واجهة React (مقرر 242)، أو خادم آخر. هؤلاء يريدون بيانات منظمة لا صفحة منسّقة. وأشهر صيغة لذلك JSON (تُنطق «جيسون»): نص بسيط يشبه كائنات JavaScript التي عرفتها في 131:
{ "id": 7, "name": "قهوة عربية", "price": 35.5, "available": true, "tags": ["مشروبات", "سعودي"], "supplier": { "name": "مزارع جازان", "city": "جازان" }}
| قيمة JSON | تقابلها في PHP |
|---|---|
كائن { "a": 1 } | مصفوفة ترابطية ['a' => 1] |
مصفوفة [1, 2] | مصفوفة مفهرسة [1, 2] |
نص "..." وعدد وقيم true / false / null | string و int/float و bool و null |
قواعد JSON صارمة: المفاتيح بين علامتي تنصيص مزدوجتين دائمًا، ولا فاصلة زائدة بعد آخر عنصر، ولا تعليقات.
٢من PHP إلى JSON: json_encode
<?php$product = [ 'id' => 7, 'name' => 'قهوة عربية', 'price' => 35.5, 'available' => true, 'tags' => ['مشروبات', 'سعودي'],]; echo json_encode($product) . "\n\n";echo json_encode($product, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
- بلا خيارات تُكتب الحروف العربية بصيغة
\u0642…: صحيحة لكنها غير مقروءة وأطول. JSON_UNESCAPED_UNICODEتبقي العربية كما هي، وJSON_PRETTY_PRINTتنسّق بأسطر ومسافات (للقراءة فقط).- العلامة
|تجمع الخيارين معًا.
٣استجابة JSON حقيقية
الواجهة التي ترد بـ JSON تخبر العميل بنوع المحتوى عبر الترويسة Content-Type: application/json، وإلا ظنها HTML. هذه أول «واجهة برمجة» API تكتبها:
<?phpheader('Content-Type: application/json; charset=utf-8'); $products = [ ['id' => 1, 'name' => 'قهوة عربية', 'price' => 35], ['id' => 2, 'name' => 'تمر سكري', 'price' => 45], ['id' => 3, 'name' => 'شاي أخضر', 'price' => 18],]; $max = isset($_GET['max']) ? (float) $_GET['max'] : null;if ($max !== null) { $products = array_values(array_filter($products, fn($p) => $p['price'] <= $max));} echo json_encode(['count' => count($products), 'data' => $products], JSON_UNESCAPED_UNICODE);
المختبر ينسّق JSON تلقائيًّا في تبويب المصدر لأن نوعه application/json. و array_filter مع دالة سهمية fn تختار المنتجات التي سعرها لا يتجاوز max، و array_values تعيد ترقيمها.
٤من JSON إلى PHP: json_decode
والاتجاه المعاكس: نص JSON يصل من طلب أو ملف أو خدمة أخرى، فنحوّله إلى مصفوفة PHP. لاحظ المعامل الثاني true: بدونه تعيد الدالة كائنات بدل مصفوفات ترابطية:
<?php$text = '{"student":"نورة","grades":[90, 85, 77],"active":true}'; $data = json_decode($text, true);echo $data['student'] . "\n";echo array_sum($data['grades']) / count($data['grades']) . "\n"; // JSON معطوب$bad = json_decode('{"name": "سعود",}', true);var_dump($bad);echo json_last_error_msg();
إن كان النص غير صالح تعيد json_decode القيمة null، وتشرح json_last_error_msg() السبب. وفي PHP الحديث يمكنك طلب استثناء بالخيار JSON_THROW_ON_ERROR.
٥استقبال JSON في الطلب
التطبيقات الحديثة ترسل بياناتها JSON في جسم الطلب بدل النماذج. هنا لا تملأ PHP مصفوفة $_POST؛ بل تقرأ الجسم الخام من php://input وتفك ترميزه بنفسك:
<?phpheader('Content-Type: application/json; charset=utf-8'); $in = json_decode(file_get_contents('php://input'), true);if (!is_array($in) || empty($in['items'])) { http_response_code(400); echo json_encode(['error' => 'أرسل JSON فيه items'], JSON_UNESCAPED_UNICODE); exit;} $total = 0;foreach ($in['items'] as $it) { $total += $it['price'] * $it['qty'];}http_response_code(201);echo json_encode(['customer' => $in['customer'] ?? 'زائر', 'total' => $total], JSON_UNESCAPED_UNICODE);
الأخطاء أيضًا تعود JSON برمز مناسب، فيفهمها البرنامج العميل بسهولة. جرّب في المختبر «📮 طلب يدوي» مع نوع البيانات JSON.
توقّع وتحقّق
لتحويل مصفوفة PHP إلى نص JSON:
encode = ترميز.ما فائدة JSON_UNESCAPED_UNICODE؟
uXXXX.json_decode($t, true) تعيد:
true.من أين نقرأ JSON المرسل في جسم الطلب؟
الخلاصة
JSONنص منظم لتبادل البيانات بين البرامج: كائنات ومصفوفات وقيم.json_encode($a, JSON_UNESCAPED_UNICODE) للإرسال، وjson_decode($t, true) للاستقبال.header('Content-Type: application/json')قبل الطباعة، ولا شيء غيرJSONفي الرد.JSONفي جسم الطلب يُقرأ منphp://inputلا من $_POST.- الأخطاء أيضًا
JSONبرمز الحالة المناسب.
تحدٍّ برمجي: واجهة إحصاءات الدرجات
متوسطاكتب stats.php: تستقبل POST بجسم JSON فيه مصفوفة درجات، وترد بإحصاءاتها JSON.
- الطلب:
{"grades": [90, 70, 80]}والرد:{"count":3,"avg":80,"max":90,"min":70}برمز 200. - المتوسط مقرّب لخانتين بـ round.
- إن لم يكن الجسم JSON صالحًا أو لم تكن grades مصفوفة غير فارغة: رمز 400 والرد
{"error":"grades مطلوبة"}. - الترويسة
Content-Type: application/jsonفي كل الردود.
👀 اعرض الاستجابة المطلوبة
POST /stats.php({"grades": [90, 70, 80]})POST /stats.php({"grades": [95, 88, 72, 61]})POST /stats.php({"grades": []})POST /stats.php(درجات)
- الكود يعمل بلا أخطاء أو تحذيرات
[90,70,80]← count 3 و avg 80 و max 90 و min 70[95,88,72,61]← avg 79- نوع المحتوى
application/json - مصفوفة فارغة ← 400
- مصفوفة فارغة ←
{"error":"grades مطلوبة"} - نص ليس JSON ← 400
- تقرأ جسم الطلب من
php://input
💡 تلميح 1
$in = json_decode(file_get_contents('php://input'), true);💡 تلميح 2
!is_array($g) || count($g) === 0 قبل أي حساب.حاول بنفسك أولًا؛ للمسألة أكثر من حلّ صحيح.
<?phpheader('Content-Type: application/json; charset=utf-8');$in = json_decode(file_get_contents('php://input'), true);$g = $in['grades'] ?? null; if (!is_array($g) || count($g) === 0) { http_response_code(400); echo json_encode(['error' => 'grades مطلوبة'], JSON_UNESCAPED_UNICODE); exit;}echo json_encode([ 'count' => count($g), 'avg' => round(array_sum($g) / count($g), 2), 'max' => max($g), 'min' => min($g),]);