تنسيق JSON في Bash: دليل jq و python3
استخدم منسق ومُجمِّل JSON المجاني مباشرةً في متصفحك — لا حاجة للتثبيت.
جرّب منسق ومُجمِّل JSON أونلاين ←عندما يبدأ سكريبت النشر في معالجة استجابات API أو التحقق من ملفات التكوين في CI، فإن معرفة كيفية تنسيق JSON في bash تصبح ضرورة سريعاً. الأداتان اللتان تغطيان 99% من الحالات الواقعية هما jq و python3 -m json.tool — كلتاهما تستطيعان تنفيذ تنسيق json bash بشكل موثوق، والتحقق من صحته بأكواد الخروج، والتكامل بنظافة في سير عمل CI/CD. للفحص لمرة واحدة بدون طرفية، يتولى الأمر فوراً منسق JSON المستند إلى المتصفح. يتناول هذا الدليل تثبيت jq، والتنسيق عبر الأنابيب والملفات، ووظائف التحقق، والتكامل مع CI/CD في GitHub Actions، وخطافات pre-commit، وأنماط heredoc، ومتى تلجأ إلى بديل مكتبة Python القياسية.
- •
jq .يُنسّق ويتحقق في آنٍ واحد — يخرج بالكود 1 عند JSON غير صالح - • استخدم
jq -eفي خطوط أنابيب CI: خروج بقيمة غير صفرية عند إخراج فارغ/false/null - •
jq . file.json > /dev/null && echo "valid"— تحقق بدون تغيير الإخراج - •
python3 -m json.toolيعمل على أي نظام بدون تثبيت إضافي - • لا تفعل أبداً
jq . f.json > f.json— الشيل يقطع الملف المصدر قبل أن يقرأه jq
ما هو تنسيق JSON في Bash؟
تنسيق JSON في bash يعني تحويل JSON المضغوط المصغّر إلى إخراج مسافته بادئة وقابل للقراءة البشرية. البيانات الأساسية لا تتغير — فقط المسافات وفواصل الأسطر تختلف. في سياقات السكريبت هذا مهم لسببين: القابلية للقراءة عند التصحيح، والتحقق عندما يتحقق المنسّق من الصياغة كتأثير جانبي. أدوات مثل jq تُحلل JSON بالكامل قبل إعادة تنسيقه، مما يعني أن تشغيل تنسيق ناجح هو أيضاً فحص ضمني للصلاحية. هذا السلوك المزدوج — التنسيق والتحقق في خطوة واحدة — هو ما يجعل jq مفيداً جداً في خطوط الأنابيب الآلية.
{
"service": "payments-api",
"version": "2.4.1",
"database": {
"host": "db-prod-01.internal",
"port": 5432,
"pool_size": 20
},
"cache": {
"enabled": true,
"ttl": 300
}
}{"service":"payments-api","version":"2.4.1","database":{"host":"db-prod-01.internal","port":5432,"pool_size":20},"cache":{"enabled":true,"ttl":300}}jq — تنسيق JSON في Bash
jq هو المعيار الفعلي لمعالجة JSON في سكريبتات الشيل (jq 1.6+, bash 4+). إنه معالج JSON سطر أوامر مخصص يمكنه تنسيق وفلترة وتحويل والتحقق من JSON. فلتر الهوية . يمرر المدخلات دون تغيير، لكن منسّقة. عندما لا يستطيع jq تحليل المدخلات يخرج بالكود 1 — هذا ما يجعله مثالياً للبرمجة النصية: التنسيق والتحقق عملية واحدة.
تثبيت jq
# macOS brew install jq # Debian / Ubuntu apt-get install -y jq # Fedora / RHEL / CentOS dnf install jq # Alpine (صور Docker) apk add --no-cache jq # التحقق jq --version # jq-1.7.1
التنسيق من stdin ومن ملف
# تمرير JSON مضمّن عبر jq
echo '{"host":"db-prod-01.internal","port":5432}' | jq .
# تنسيق ملف مباشرة (يطبع على stdout)
jq . config/feature-flags.json
# تنسيق بمسافة بادئة 4 مسافات
jq --indent 4 . config/feature-flags.json
# تنسيق باستخدام جدولة بدلاً من مسافات
jq --tab . config/feature-flags.jsonكتابة الإخراج المنسّق إلى ملف
# حفظ الإخراج المنسّق (لا تعيد التوجيه إلى نفس الملف) jq . compact.json > formatted.json # مضغوط (تصغير) — عكس التنسيق jq -c . formatted.json
jq يخرج بالكود 1 عند JSON غير صالح، الكود 0 عند النجاح، والكود 5 عند أخطاء الاستخدام. استخدم هذا في جمل if وحراس || exit 1 في جميع أنحاء سكريبتاتك.فرز المفاتيح وإزالة الألوان
# فرز جميع المفاتيح أبجدياً (مفيد للفروق الحتمية) jq --sort-keys . config/app-config.json # تعطيل إخراج الألوان عند الكتابة إلى ملف سجل jq --monochrome-output . response.json >> deploy.log
مرجع خيارات jq
أكثر علامات jq استخداماً لسير عمل التنسيق والتحقق:
التحقق من JSON في سكريبت Bash
التحقق والتنسيق هما نفس العملية في jq — يُحلّل قبل أن يطبع. أعد توجيه stdout إلى /dev/null عندما تريد فقط كود الخروج بدون الإخراج المنسّق. النمط أدناه قابل لإعادة الاستخدام عبر سكريبتات النشر وخطافات pre-commit وخطوط أنابيب CI. في الاستجابة للحوادث، أول شيء أفعله مع حمولة API غير مألوفة هو تمريرها عبر jq — يحوّل جداراً من JSON المضغوط إلى شيء يمكنني قراءته وتصحيحه فعلاً.
دالة تحقق قابلة لإعادة الاستخدام
validate_json() {
local file="$1"
if jq . "$file" > /dev/null 2>&1; then
echo "✓ JSON صالح: $file"
return 0
else
echo "✗ JSON غير صالح: $file" >&2
return 1
fi
}إيقاف النشر عند تكوين غير صالح
CONFIG="infra/k8s/app-config.json"
validate_json "$CONFIG" || { echo "إلغاء النشر: تكوين غير صالح" >&2; exit 1; }التحقق من جميع ملفات JSON في مجلد
find ./config -name "*.json" | while read -r f; do jq . "$f" > /dev/null 2>&1 || echo "غير صالح: $f" done
-e / --exit-status تذهب أبعد من ذلك: تخرج أيضاً بالكود 1 عندما يكون الإخراج false أو null. استخدمها للتأكيد أن حقلاً معيناً صحيح: jq -e '.feature_flags.new_checkout' config.json.تنسيق JSON من الملفات واستجابات API
مصدران شائعان لـ JSON في سكريبتات الشيل هما الملفات على القرص واستجابات HTTP API عبر curl. لكل منهما نمط معالجة مختلف قليلاً. بالنسبة للملفات، المخاوف الرئيسية هي التحرير الآمن في المكان. بالنسبة لاستجابات API، التفصيل الأساسي هو تعطيم شريط تقدم curl حتى لا يفسد مدخلات jq.
التنسيق الآمن في المكان لملف
# تنسيق وكتابة آمنة باستخدام ملف مؤقت tmp=$(mktemp) jq --indent 2 . config/feature-flags.json > "$tmp" && mv "$tmp" config/feature-flags.json echo "تم تنسيق config/feature-flags.json"
تنسيق استجابة curl API
# تنسيق حالة النشر من API DEPLOY_ID="dep_8f3a2b9c" curl -s \ -H "Authorization: Bearer $DEPLOY_API_TOKEN" \ "https://api.deployments.internal/v1/deploys/$DEPLOY_ID" \ | jq --indent 2 .
التنسيق والفلترة في آنٍ واحد
# الحصول على منسّق + الفلترة للأخطاء فقط من نقطة نهاية المراقبة
curl -s "https://monitoring.internal/api/events?level=error&limit=10" \
| jq '[.events[] | {id, message, timestamp, service}]' \
|| { echo "فشل في جلب أو تحليل الأحداث" >&2; exit 1; }نمط || { ... } بالغ الأهمية هنا. بدونه، يمر curl فاشل أو استجابة API مشوهة بصمت، والخطوة التالية في سكريبتك تعمل على بيانات فارغة أو جزئية. إذا كنت تحتاج لفحص استجابات متداخلة معقدة دون كتابة تعبير فلتر أولاً، فإن منسق JSON المستند إلى المتصفح يتيح لك لصق الاستجابة الخام والتنقل في الشجرة بشكل تفاعلي.
تنسيق JSON في خطوط أنابيب CI/CD
CI هو المكان الذي تهم فيه بوابات التحقق من JSON أكثر — تكوين مشوّه يصل إلى الإنتاج أكثر إيلاماً بكثير من فشل خط الأنابيب. معظم المنافسين يوثّقون jq للاستخدام الفردي في الطرفية؛ الأنماط التالية هي التي أستخدمها في سير عمل SRE الإنتاجي لاكتشاف أخطاء التكوين قبل أن تصل إلى أي فتحة نشر.
GitHub Actions — التحقق من جميع تكوينات JSON
- name: التحقق من تكوينات JSON
run: |
echo "جارٍ التحقق من ملفات تكوين JSON..."
find . -name "*.json" -not -path "*/node_modules/*" | while read -r f; do
if ! jq . "$f" > /dev/null 2>&1; then
echo "::error file=$f::صياغة JSON غير صالحة"
exit 1
fi
done
echo "جميع ملفات JSON صالحة"خطاف pre-commit — التحقق من ملفات JSON المرحلية
#!/usr/bin/env bash
set -euo pipefail
STAGED=$(git diff --cached --name-only --diff-filter=ACM | grep '\.json$' || true)
[ -z "$STAGED" ] && exit 0
for f in $STAGED; do
jq . "$f" > /dev/null 2>&1 || { echo "JSON غير صالح: $f"; exit 1; }
done
echo "اجتاز التحقق من JSON"scripts/validate-json.sh، اجعله قابلاً للتنفيذ بـ chmod +x scripts/validate-json.sh، ثم أنشئ رابطاً رمزياً: ln -s ../../scripts/validate-json.sh .git/hooks/pre-commit.تنسيق متغيرات JSON و Heredocs في Bash
غالباً ما تبني سكريبتات الشيل حمولات JSON ديناميكياً — من متغيرات البيئة، أو بيانات git الوصفية، أو القيم المحسوبة. النمط الأكثر أماناً هو jq -n --arg / --argjson بدلاً من الإقحام النصي الذي ينكسر في اللحظة التي تحتوي فيها قيمة على علامة اقتباس أو سطر جديد. اقتبس دائماً المتغيرات بعلامتي اقتباس عند التمرير إلى jq لمنع تقسيم الكلمات على المسافات في JSON.
تنسيق متغير استجابة API مخزّن
# اقتبس دائماً "$API_RESPONSE" — المسافات في JSON ستكسر التوسيع غير المقتبس echo "$API_RESPONSE" | jq --indent 2 .
بناء وتنسيق حمولة باستخدام jq -n
payload=$(jq -n \
--arg env "production" \
--arg version "$(git describe --tags)" \
--argjson replicas 3 \
'{environment: $env, version: $version, replicas: $replicas}')
# فحص الحمولة المبنية
echo "$payload" | jq .
# إرسالها إلى API
curl -s -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $DEPLOY_API_TOKEN" \
-d "$payload" \
"https://api.deployments.internal/v1/deploys"--arg يربط دائماً قيمة سلسلة. --argjson يُحلّل القيمة كـ JSON أولاً، حتى تتمكن من تمرير الأرقام والقيم المنطقية والمصفوفات والكائنات بدون اقتباس داخل تعبير الفلتر.تنسيق JSON في Bash بدون تثبيت jq
عندما لا يكون jq متاحاً — صور Docker الدنيا، أجهزة تشغيل CI المقيّدة، أو أنظمة حيث لا تستطيع تثبيت الحزم — توفر وحدة json.tool المدمجة في Python نفس القدرة الأساسية. إنها جزء من مكتبة Python القياسية؛ إذا كان Python 3 مثبتاً، فإنها تعمل بدون تبعيات إضافية.
# تنسيق من ملف python3 -m json.tool config.json # التحكم في عرض المسافة البادئة python3 -m json.tool --indent 2 config.json # فرز المفاتيح أبجدياً python3 -m json.tool --sort-keys config.json # تنسيق من stdin (مثل التمرير من curl) curl -s https://api.deployments.internal/v1/status | python3 -m json.tool
python3 -m json.tool أكثر صرامة من jq: يرفض الفواصل الزائدة والتعليقات وامتدادات JSON5. هذه الصرامة مرغوبة للتحقق من تكوين الإنتاج لكن يمكن أن تكون نقطة احتكاك عند العمل مع JSON متساهل من أدوات طرف ثالث. كما أنه لا ينتج إخراجاً ملوناً، مما يجعل الفحص الطرفي أقل راحة من jq للاستخدام التفاعلي.# التحقق بكود الخروج (نفس دلالات jq)
python3 -m json.tool config.json > /dev/null && echo "صالح" || echo "غير صالح"
# التحقق من سلسلة مضمّنة
echo '{"service":"payments-api","healthy":true}' | python3 -m json.tool > /dev/null
echo "كود الخروج: $?" # 0 = صالحإخراج الطرفية مع تمييز الصياغة
jq يُلوّن إخراجه افتراضياً — المفاتيح بالأزرق، والسلاسل بالأخضر، والأرقام بالأبيض. عندما تحتاج إلى تمييز كامل لصياغة JSON في صفحة قابلة للتمرير، أو عند تصحيح استجابات متداخلة كبيرة في جلسة طرفية، bat يوفر التجربة الأكثر راحة. كلاهما مفيد للتصحيح والفحص التفاعلي؛ لا ينبغي استخدام أيٍّ منهما عند كتابة الإخراج إلى ملفات أو استجابات API.
تثبيت bat
# macOS brew install bat # Debian / Ubuntu (قد يُسمى الثنائي batcat — أضف اسماً مستعاراً إذا لزم) apt-get install -y bat # alias bat=batcat # أضف إلى ~/.bashrc إذا لزم # التحقق bat --version # bat 0.24.0
عرض ملفات JSON مع تمييز الصياغة
# JSON بتمييز صياغة في الصفحة (اضغط q للخروج) bat config/app-config.json # تعطيل الصفحة — طباعة مباشرة إلى الطرفية bat --paging=never config/app-config.json # تمرير إخراج jq عبر bat للفحص الملوّن jq '.database' infra/app-config.json | bat --language=json --paging=never
إخراج jq ملوّن في صفحة قابلة للتمرير
# -C يفرض الألوان حتى عندما لا يكون stdout طرفياً (مثلاً عند التمرير إلى less) jq -C . logs/deploy-response.json | less -R
bat / jq -C) فقط للفحص الطرفي والتصحيح. جرّد رموز ألوان ANSI قبل الكتابة إلى ملفات السجل أو التمرير إلى أدوات أخرى — استخدم jq -M . (--monochrome-output) أو bat --plain.العمل مع ملفات JSON الكبيرة في Bash
عندما يتجاوز ملف JSON 50–100 ميغابايت، قد يكون تحميله في الذاكرة بالوضع الافتراضي لـ jq بطيئاً أو يؤدي إلى نفاد الذاكرة على مضيفين محدودي الذاكرة (حاويات Docker بحد 512 ميغابايت، على سبيل المثال). jq --stream يصدر أزواج المسار/القيمة بشكل تدريجي أثناء القراءة، دون تخزين المستند بالكامل مؤقتاً. بالنسبة لـ NDJSON (كائن JSON واحد لكل سطر)، لدى jq نهج أصلي أكثر كفاءة.
تدفق ملف JSON كبير باستخدام jq --stream
# --stream يصدر أزواج [مسار، قيمة مقياسية] أثناء قراءة jq للمدخلات # استخراج جميع حقول "status" من أرشيف سجل كبير دون تحميله بالكامل jq -c --stream 'if length == 2 and (.[0][-1] == "status") then .[1] else empty end' logs/archive-2026-03.json
NDJSON / JSON Lines — معالجة كائن واحد لكل سطر
# NDJSON: كائن JSON واحد لكل سطر — شائع في صادرات Kafka و Fluentd و Logstash
# -R يقرأ الأسطر الخام؛ fromjson? يتخطى الأسطر غير الصالحة كـ JSON
jq -c -R 'fromjson? | {id: .request_id, status: .http_status, latency: .duration_ms}' logs/access-2026-03-13.ndjson > logs/summary.ndjson# بديل حلقة الشيل — مفيد عند الحاجة لمعالجة أخطاء لكل سطر
while IFS= read -r line; do
echo "$line" | jq -c '{id: .request_id, status: .http_status}' 2>/dev/null || echo "تخطي: سطر مشوّه" >&2
done < logs/access-2026-03-13.ndjsonjq . file.json القياسي إلى --stream عندما يكون الملف أكبر من 50–100 ميغابايت أو عندما تعمل العملية داخل حاوية بحد ذاكرة. بالنسبة لخطوط أنابيب NDJSON، فضّل jq -R 'fromjson?' على حلقة while read في الشيل — إنه أسرع بشكل ملحوظ لأنه يتجنب إنشاء shell فرعي لكل سطر.الأخطاء الشائعة
المشكلة: يفتح الشيل ملف الإخراج ويقطعه قبل أن يقرأ jq المدخلات. إذا كان المصدر والوجهة نفس المسار، يقرأ jq ملفاً فارغاً.
الحل: اكتب إلى ملف مؤقت mktemp أولاً، ثم استبدل الأصل بشكل ذري باستخدام mv.
tmp=$(mktemp) && jq --indent 2 . settings.json > "$tmp" && mv "$tmp" settings.json
jq --indent 2 . settings.json > settings.json
المشكلة: بدون معالج أخطاء، يستمر السكريبت بصمت مع ملف منسّق فارغ أو مفقود عندما يكون JSON غير صالح — الخطوات اللاحقة تفشل بأخطاء محيّرة.
الحل: أضف || { echo '...' >&2; exit 1; } بعد كل استدعاء jq ينتج إخراجاً تستخدمه خطوة لاحقة.
jq . response.json > formatted.json || { echo "JSON غير صالح في response.json" >&2; exit 1; }jq . response.json > formatted.json
المشكلة: curl يطبع شريط تقدم على stderr افتراضياً. عندما يُدمج stderr مع stdout (مثلاً في shells فرعية أو التقاط السجلات)، يظهر نص شريط التقدم في مدخلات jq ويسبب خطأ في التحليل.
الحل: مرّر دائماً -s (صامت) إلى curl عند التمرير إلى jq. استخدم -v أو --fail-with-body بشكل منفصل إذا احتجت لإخراج تشخيصي.
curl -s https://api.payments.internal/config | jq .
curl https://api.payments.internal/config | jq .
المشكلة: علامة -r / --raw-output تزيل علامات اقتباس سلاسل JSON من قيم السلاسل ذات المستوى الأعلى — لا تنسّق الكائنات أو المصفوفات. تمرير -r . لمدخلات كائن ينتج نفس الكائن المضغوط، وليس إخراجاً بمسافات بادئة.
الحل: استخدم jq . (بدون علامة -r) للتنسيق. احتفظ بـ -r لاستخراج قيم السلاسل العادية مثل jq -r '.version' config.json.
jq . config.json
jq -r . config.json
jq مقابل python3 مقابل json_pp — مقارنة سريعة
الاختيار بين الأدوات يعتمد على ما هو متاح في بيئتك وما تحتاجه بعيداً عن التنسيق الأساسي:
لمعظم أعمال البرمجة النصية في bash وCI/CD، jq هو الخيار الافتراضي الصحيح — يتحقق ويُنسّق ويفلتر ويوفر أكواد خروج موثوقة في ثنائي واحد بدون تبعية وقت تشغيل. ارجع إلى python3 -m json.tool عندما لا تستطيع تثبيت حزم إضافية وكان Python موجوداً بالفعل.
الأسئلة الشائعة
كيف أنسّق ملف JSON في مكانه باستخدام bash؟
لا تعيد توجيه إخراج jq مطلقاً إلى نفس الملف — الشيل يقطع الملف قبل أن يقرأه jq. بدلاً من ذلك، اكتب إلى ملف مؤقت أولاً، ثم استبدل الأصل بشكل ذري باستخدام mv.
tmp=$(mktemp) jq --indent 2 . config/app-config.json > "$tmp" && mv "$tmp" config/app-config.json echo "تم التنسيق في المكان بنجاح"
كيف أتحقق من صحة JSON في سكريبت bash وأخرج عند حدوث خطأ؟
مرّر الملف إلى jq وأعد توجيه stdout إلى /dev/null. استخدم || للتقاط الخروج بقيمة غير صفرية وإيقاف السكريبت. يخرج jq بالكود 1 عند أي خطأ في التحليل، مما يجعله موثوقاً لبوابات CI.
validate_json() {
local file="$1"
if jq . "$file" > /dev/null 2>&1; then
echo "✓ JSON صالح: $file"
return 0
else
echo "✗ JSON غير صالح: $file" >&2
return 1
fi
}
validate_json infra/k8s/app-config.json || exit 1كيف أنسّق JSON في bash دون تثبيت jq؟
استخدم وحدة json.tool المدمجة في python3 — تأتي مع كل تثبيت Python قياسي وتنتج إخراجاً بمسافة بادئة صحيحة بنفس دلالات كود الخروج كـ jq.
# تنسيق من ملف python3 -m json.tool config.json # تنسيق من stdin (مثل استجابة curl) curl -s https://api.internal/status | python3 -m json.tool --indent 2
كيف أنسّق JSON من استجابة curl في bash؟
مرّر دائماً -s (صامت) إلى curl حتى لا تفسد أشرطة التقدم مدخلات jq. مرّر stdout الخاص بـ curl مباشرة إلى jq.
DEPLOY_ID="dep_8f3a2b9c" curl -s \ -H "Authorization: Bearer $DEPLOY_API_TOKEN" \ "https://api.deployments.internal/v1/deploys/$DEPLOY_ID" \ | jq --indent 2 .
كيف أنسّق جزءاً فقط من ملف JSON باستخدام jq؟
استخدم تعبير مسار jq بدلاً من فلتر الهوية (.) لاستخراج وتنسيق كائن أو مصفوفة متداخلة. النتيجة نفسها هي JSON منسّق.
# تنسيق كتلة تكوين قاعدة البيانات فقط
jq --indent 2 '.database' infra/app-config.json
# تنسيق + تصفية مصفوفة الأحداث إلى مستوى الخطأ فقط
jq '[.events[] | select(.level == "error") | {id, message, service}]' events.jsonما كود الخروج الذي يعيده jq لـ JSON غير صالح؟
يخرج jq بالكود 1 لأي خطأ في التحليل وأيضاً عندما تكون علامة -e / --exit-status مضبوطة والإخراج false أو null. كود الخروج 0 يعني تم تحليل JSON صالح وأنتج إخراجاً صحيحاً. كود الخروج 5 يعني واجه النظام خطأ في الاستخدام.
# اختبار كود الخروج مباشرة
echo '{"ok":true}' | jq . > /dev/null 2>&1; echo "exit: $?" # exit: 0
echo '{bad json}' | jq . > /dev/null 2>&1; echo "exit: $?" # exit: 1
# علامة -e: اخرج بـ 1 إذا كان الإخراج false/null
echo 'null' | jq -e . > /dev/null 2>&1; echo "exit: $?" # exit: 1أدوات ذات صلة
بدائل ومكملات مستندة إلى المتصفح لتنسيق JSON في bash — مفيدة عندما تحتاج إلى واجهة مرئية، أو رابط قابل للمشاركة، أو عند العمل خارج الطرفية:
Nadia is a site reliability engineer who lives in the terminal. She writes Bash scripts that process logs, transform data, and orchestrate infrastructure across fleets of servers. She is a heavy user of jq, awk, and sed and writes about shell one-liners, text processing pipelines, data serialisation from the command line, and the practical Bash patterns that SREs reach for when speed matters more than elegance.
Erik is a DevOps engineer who has spent years writing and maintaining the shell scripts that hold CI/CD pipelines together. He writes about Bash best practices, portable POSIX shell, encoding and decoding in shell scripts, secret management from the command line, and the patterns that separate reliable automation scripts from brittle ones. He is a strong believer in making shell scripts readable and testable with tools like bats-core.