JSON Formatter Python — دليل json.dumps()

·Backend Developer·مراجعة بواسطةDmitri Volkov·نُشر

استخدم منسق ومُجمِّل JSON المجاني مباشرةً في متصفحك — لا حاجة للتثبيت.

جرّب منسق ومُجمِّل JSON أونلاين ←

عندما أقوم بتصحيح أخطاء عميل Python API، أول شيء أتوجه إليه هو طباعة JSON بشكل منسق في Python — استدعاء واحد لـ json.dumps(data, indent=4) ويتحول كتلة النص غير المقروءة في سطر واحد إلى شيء يمكن التنقل فيه بسهولة. الوحدة المدمجة json في Python تتعامل مع هذا كليًا في المكتبة القياسية — لا حاجة لتثبيت أي حزمة خارجية. إذا كنت تحتاج فقط إلى نتيجة سريعة دون كتابة أي كود، فإن JSON Formatter من ToolDeck يقوم بذلك فوراً. يغطي هذا الدليل كل الأساليب العملية: json.dumps() بجميع معاملاتها، وpprint، وorjson للتنسيق عالي الأداء، وأداة json.tool من سطر الأوامر، وسيناريوهات عملية مثل تنسيق استجابات API والقراءة من القرص — كل ذلك مع كود متوافق مع Python 3.8+. يغطي أيضًا تسلسل الأنواع المخصصة مثل datetime وUUID، وبث الملفات بحجم الغيغابايت مع ijson، وتمييز الصياغة في الطرفية مع rich.

النقاط الرئيسية
  • json.dumps(data, indent=4) مدمج في المكتبة القياسية لـ Python منذ الإصدار 2.6 — لا حاجة لأي تثبيت.
  • مرر ensure_ascii=False في كل مرة تحتوي فيها بياناتك على أحرف عربية أو مُعربة أو أحرف CJK أو رموز تعبيرية.
  • بالنسبة لـ datetime وUUID أو الفئات المخصصة، استخدم المعامل default= أو قم بتوسيع json.JSONEncoder.
  • separators=(',', ':') يزيل كل المسافات — استخدمه لنقل الشبكة أو التضمين في URL.
  • orjson أسرع 5–10× من المكتبة القياسية ويتعامل أصليًا مع datetime وuuid.UUID.
  • pprint.pprint() يُخرج صياغة Python (True/None)، وليس JSON صالحًا — لا تستخدمه أبدًا للملفات أو استجابات API.
  • بالنسبة لملفات JSON أكبر من 50 ميغابايت، استخدم البث مع ijson بدلًا من json.load() لتجنب MemoryError.

ما هي طباعة JSON المنسقة؟

تحوّل الطباعة المنسقة سلسلة JSON مضغوطة ومصغّرة إلى تنسيق مقروء مع مسافة بادئة ثابتة وفواصل أسطر. هذا التحويل مجرد تجميل: البيانات متطابقة، يتغير العرض فقط. وحدة json في Python تتعامل مع هذا بالكامل في المكتبة القياسية — لا شيء لتثبيته.

After · json
Before · json
{
    "id": "usr_9f3a2b",
    "name": "أحمد محمد",
    "roles": [
        "admin",
        "editor"
    ],
    "prefs": {
        "theme": "dark",
        "lang": "ar"
    }
}
{"id":"usr_9f3a2b","name":"أحمد محمد","roles":["admin","editor"],"prefs":{"theme":"dark","lang":"ar"}}

json.dumps() — الطريقة القياسية لتنسيق JSON

json.dumps() جزء من المكتبة القياسية لـ Python منذ الإصدار 2.6 — فقط import json، لا تثبيت مطلوب. تُسلسل أي كائن Python متوافق مع JSON إلى سلسلة نصية منسقة. المعامل الأساسي هو indent: اضبطه على 4 (أو 2) للحصول على مخرجات مقروءة.

Python 3.8+ — مثال بسيط
import json

user = {
    "id": "usr_9f3a2b",
    "name": "أحمد محمد",
    "roles": ["admin", "editor"],
    "prefs": {"theme": "dark", "lang": "ar"}
}

print(json.dumps(user, indent=4, ensure_ascii=False))
# الإخراج:
# {
#     "id": "usr_9f3a2b",
#     "name": "أحمد محمد",
#     "roles": [
#         "admin",
#         "editor"
#     ],
#     "prefs": {
#         "theme": "dark",
#         "lang": "ar"
#     }
# }

للاستخدام في الإنتاج، ستحتاج غالبًا إلى sort_keys=True (مخرجات ثابتة عبر التشغيلات) و ensure_ascii=False (الحفاظ على الأحرف غير ASCII مقروءة):

Python 3.8+ — مع sort_keys و ensure_ascii
import json

api_response = {
    "timestamp": "2024-05-01T10:30:00Z",
    "status": "success",
    "data": {
        "user_id": "usr_9f3a2b",
        "display_name": "فاطمة علي",
        "city": "الرياض",
        "score": 4892.5,
        "tags": ["python", "backend", "api"]
    }
}

print(json.dumps(api_response, indent=4, sort_keys=True, ensure_ascii=False))
# الإخراج (مفاتيح مرتبة، أحرف عربية محفوظة):
# {
#     "data": {
#         "city": "الرياض",
#         "display_name": "فاطمة علي",
#         "score": 4892.5,
#         "tags": ["api", "backend", "python"],
#         "user_id": "usr_9f3a2b"
#     },
#     "status": "success",
#     "timestamp": "2024-05-01T10:30:00Z"
# }
ملاحظة:json.dumps() تُعيد سلسلة نصية. لكتابة JSON منسق مباشرة إلى ملف، استخدم json.dump(data, f, indent=4) (بدون s) — تكتب إلى كائن ملف وتتجنب إنشاء سلسلة نصية وسيطة في الذاكرة.

مرجع معاملات json.dumps()

جميع المعاملات اختيارية ما عدا الكائن نفسه. القيم الافتراضية تُنتج JSON مضغوطًا وآمنًا للـ ASCII — مرر المعاملات صراحةً للحصول على مخرجات مقروءة للإنسان.

المعامل
النوع
الافتراضي
الوصف
obj
any
كائن Python المراد تسلسله إلى سلسلة نصية بتنسيق JSON.
indent
int | str | None
None
المسافات لكل مستوى مسافة بادئة. None = سطر واحد مضغوط، 0 = فواصل أسطر فقط، 4 = معياري.
sort_keys
bool
False
ترتيب مفاتيح القاموس أبجديًا عبر جميع المستويات المتداخلة.
ensure_ascii
bool
True
هروب من الأحرف غير ASCII إلى \uXXXX. اضبطه على False للحفاظ على أحرف Unicode كما هي.
separators
tuple | None
None
زوج (فاصل_العناصر، فاصل_المفاتيح). استخدم (",", ":") للحصول على أكثر مخرجات مضغوطة.
default
callable | None
None
يُستدعى للأنواع غير القابلة للتسلسل. ارمِ TypeError لرفض القيمة.
allow_nan
bool
True
تسلسل float("nan") و float("inf") كقيم JS حرفية. اضبطه على False لرمي ValueError.

مخرجات JSON المضغوطة مع المعامل separators

بشكل افتراضي، تفصل json.dumps() العناصر بـ ", " والمفاتيح عن القيم بـ ": ". يُتيح المعامل separators تجاوز كليهما. تمرير (',', ':') يُزيل كل المسافات لإنتاج أكثر JSON صالح مضغوطًا — مفيد لنقل الشبكة أو تضمين URL أو تخزين JSON في عمود قاعدة بيانات حيث يُحسب كل بايت.

Python 3.8+
import json

payload = {
    "endpoint": "/api/v2/events",
    "filters": {"status": "active", "limit": 100},
    "sort": "desc"
}

# افتراضي — مسافات بعد الفواصل (مقروء)
default_out = json.dumps(payload)
# {"endpoint": "/api/v2/events", "filters": {"status": "active", "limit": 100}, "sort": "desc"}
# len = 88

# مضغوط — بدون مسافات
compact_out = json.dumps(payload, separators=(',', ':'))
# {"endpoint":"/api/v2/events","filters":{"status":"active","limit":100},"sort":"desc"}
# len = 80  (أصغر بنسبة 9%؛ المدخرات تكبر مع الحمولات الأكبر والأعمق)

# مضغوط + مفاتيح مرتبة لمفاتيح تخزين مؤقت قابلة للتكرار
canonical = json.dumps(payload, separators=(',', ':'), sort_keys=True)
print(canonical)
# {"endpoint":"/api/v2/events","filters":{"limit":100,"status":"active"},"sort":"desc"}
ملاحظة:عند تمرير indent= مع separators=، يتحكم separators فقط في الفواصل المضمنة — تبقى فواصل الأسطر والمسافات البادئة من indent محفوظة. إذا أردت مخرجات مضغوطة في سطر واحد، احذف indent (أو مرر None) واضبط separators=(',', ':').

تسلسل كائنات Python المخصصة مع المعامل default

الوحدة القياسية json تُسلسل القواميس والقوائم والسلاسل النصية والأرقام والقيم المنطقية و None — لكنها ترميTypeError لأي نوع آخر. أكثر المذنبين شيوعًا في كود الإنتاج هما كائنات datetime وUUID.

Python 3.8+ — TypeError بدون معالجة مخصصة
import json
from datetime import datetime, timezone
import uuid

order = {
    "order_id": uuid.uuid4(),            # ❌ TypeError: UUID is not JSON serializable
    "placed_at": datetime.now(timezone.utc),  # ❌ TypeError: datetime is not JSON serializable
    "total_usd": 142.50,
    "items": ["pro-subscription", "addon-storage"]
}

json.dumps(order)  # يرمي TypeError

الأسلوب 1 — المعامل default=

مرر callable إلى default=. json.dumps() تستدعيه لأي كائن لا تستطيع معالجته. أعد تمثيلًا قابلًا للتسلسل، أو ارمِ TypeError للأنواع التي لا تدعمها صراحةً — لا تتجاهل أبدًا الأنواع غير المعروفة بصمت.

Python 3.8+
import json
from datetime import datetime, timezone, date
import uuid
from decimal import Decimal

def json_default(obj):
    if isinstance(obj, (datetime, date)):
        return obj.isoformat()
    if isinstance(obj, uuid.UUID):
        return str(obj)
    if isinstance(obj, Decimal):
        return float(obj)
    raise TypeError(f"Type {type(obj).__name__!r} is not JSON serializable")

order = {
    "order_id": uuid.uuid4(),
    "placed_at": datetime(2024, 5, 1, 10, 30, 0, tzinfo=timezone.utc),
    "total_usd": Decimal("142.50"),
    "items": ["pro-subscription", "addon-storage"]
}

print(json.dumps(order, indent=4, default=json_default))
# {
#     "order_id": "a3f1c2d4-e5b6-7890-abcd-ef1234567890",
#     "placed_at": "2024-05-01T10:30:00+00:00",
#     "total_usd": 142.5,
#     "items": ["pro-subscription", "addon-storage"]
# }

الأسلوب 2 — توسيع json.JSONEncoder

لمنطق ترميز قابل لإعادة الاستخدام ومشترك عبر وحدات متعددة، يُعدّ توسيع json.JSONEncoder أنظف من تمرير دالة default في كل مكان. تجاوز الأسلوب default واستدعِ super().default(obj) كملاذ أخير — هذا يحافظ على سلوك الخطأ الصحيح للأنواع غير المدعومة.

Python 3.8+
import json
from datetime import datetime, timezone
import uuid
from decimal import Decimal

class AppEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime):
            return obj.isoformat()
        if isinstance(obj, uuid.UUID):
            return str(obj)
        if isinstance(obj, Decimal):
            return float(obj)
        return super().default(obj)  # يرمي TypeError للأنواع غير المعروفة

order = {
    "order_id": uuid.uuid4(),
    "placed_at": datetime(2024, 5, 1, 10, 30, 0, tzinfo=timezone.utc),
    "total_usd": Decimal("142.50"),
}

# مرر فئة المُشفِّر عبر cls=
print(json.dumps(order, indent=4, cls=AppEncoder))
# مخرجات مطابقة لأسلوب default=
ملاحظة:استدعِ دائمًا super().default(obj) (أو ارمِ TypeError صراحةً) للأنواع غير المعروفة. إعادة str(obj) بصمت لكل شيء ستُفسد الكائنات التي كان يجب أن ترمي خطأً — وهو خطأ يصعب تتبعه في الإنتاج.

فك التشفير — object_hook

الترميز نصف القصة فقط. لإعادة بناء كائن Python مخصص من JSON، مرر دالة object_hook إلى json.loads() أو json.load(). يُستدعى الـ hook لكل كائن JSON مُفكَّك (قاموس) ويمكنه إعادة أي قيمة Python بدلًا منه — مما يمنحك دورة كاملة للترميز ↔ فك الترميز.

Python 3.8+
import json
from datetime import datetime
from dataclasses import dataclass

@dataclass
class Event:
    name: str
    occurred_at: datetime
    user_id: str

def encode_event(obj):
    if isinstance(obj, Event):
        return {
            "__type__": "Event",
            "name": obj.name,
            "occurred_at": obj.occurred_at.isoformat(),
            "user_id": obj.user_id,
        }
    raise TypeError(f"Cannot serialize {type(obj)}")

def decode_event(d):
    if d.get("__type__") == "Event":
        return Event(
            name=d["name"],
            occurred_at=datetime.fromisoformat(d["occurred_at"]),
            user_id=d["user_id"],
        )
    return d

# الترميز
event = Event("login", datetime(2024, 5, 1, 10, 30), "usr_9f3a2b")
json_str = json.dumps(event, default=encode_event, indent=4)

# فك الترميز إلى نسخة Event
restored = json.loads(json_str, object_hook=decode_event)
print(type(restored))           # <class 'Event'>
print(restored.occurred_at)     # 2024-05-01 10:30:00
ملاحظة:يُستدعى object_hook لكل قاموس متداخل في المستند — وليس فقط المستوى الأعلى. أدرج حقل تمييزي (مثل "__type__") لكي يستطيع الـ hook التمييز بين كائناتك المخصصة والقواميس العادية التي يجب تركها كما هي.

pprint — الوحدة البديلة (ومتى لا تستخدمها)

وحدة pprint في Python (طابعة مُنسّقة) تُنسّق هياكل بيانات Python لسهولة القراءة في الطرفية. تعمل على كائنات Python المُحللة، وليس على سلاسل JSON النصية — ومخرجاتها تستخدم صياغة Python، وليس صياغة JSON.

Python 3.8+
import json, pprint

raw = '{"sensor_id":"s-441","readings":[23.1,23.4,22.9],"unit":"celsius","active":true}'
data = json.loads(raw)

# pprint — repr Python صالح، وليس JSON صالحًا
pprint.pprint(data, sort_dicts=False)
# {'sensor_id': 's-441',
#  'readings': [23.1, 23.4, 22.9],
#  'unit': 'celsius',
#  'active': True}        ← Python True، وليس JSON true

# json.dumps — JSON صالح
print(json.dumps(data, indent=4))
# {
#     "sensor_id": "s-441",
#     "readings": [23.1, 23.4, 22.9],
#     "unit": "celsius",
#     "active": true      ← JSON صالح
# }
تحذير:لا ترسل أبدًا مخرجات pprint إلى نقطة نهاية API أو تكتبها إلى ملف .json — ستُعطل أي محلل JSON يتوقع صياغة قياسية. استخدم json.dumps(indent=4) لجميع المخرجات التي يجب أن تكون JSON صالحًا.

متى يكون pprint منطقيًا: الفحص السريع في الطرفية لكائنات Python في REPL أو سجل تصحيح، خاصةً عندما يحتوي الكائن على أنواع غير قابلة للتسلسل في JSON (مجموعات، نسخ فئات مخصصة، dataclasses قبل التحويل).

كيفية طباعة استجابة JSON من Requests بشكل منسق

السيناريو الأكثر شيوعًا في العالم الحقيقي: لديك ملف JSON على القرص أو استجابة HTTP من API، وتريد تنسيقها للتصحيح أو التسجيل. كلا الحالتين يستخدمان نفس النهج — التحليل إلى قاموس Python، ثم التنسيق مع json.dumps().

القراءة من ملف

Python 3.8+
import json

try:
    with open("config.json", "r", encoding="utf-8") as f:
        data = json.load(f)

    # طباعة منسقة في الطرفية
    print(json.dumps(data, indent=4, ensure_ascii=False))

    # أو كتابة النسخة المنسقة مرة أخرى إلى القرص
    with open("config.pretty.json", "w", encoding="utf-8") as f:
        json.dump(data, f, indent=4, ensure_ascii=False)

except json.JSONDecodeError as e:
    print(f"JSON غير صالح: {e}")
except FileNotFoundError:
    print(f"الملف غير موجود: config.json")

تنسيق استجابة API

Python 3.8+ (يتطلب: pip install requests)
import json, requests
from requests.exceptions import HTTPError, ConnectionError, Timeout

def pretty_print_api(url: str) -> None:
    try:
        resp = requests.get(url, timeout=10)
        resp.raise_for_status()
        print(json.dumps(resp.json(), indent=4, ensure_ascii=False))
    except HTTPError as e:
        print(f"HTTP {e.response.status_code}: {e}")
    except (ConnectionError, Timeout) as e:
        print(f"خطأ في الشبكة: {e}")
    except json.JSONDecodeError:
        print(f"جسم الاستجابة ليس JSON:\n{resp.text[:500]}")

pretty_print_api("https://api.github.com/repos/python/cpython")
ملاحظة:response.json() تُحلل جسم الاستجابة مسبقًا — لا حاجة لاستدعاء json.loads() منفصلًا. أضف دائمًا raise_for_status() قبل الوصول إلى .json() لاصطياد أخطاء 4xx/5xx قبل أن تتسبب في خطأ تحليل مُربك.

الطباعة المنسقة من سطر الأوامر

Python يأتي مع json.tool، وحدة CLI لتنسيق JSON مباشرة من الطرفية — لا يلزم أي سكريبت Python. متاحة على أي جهاز مثبت عليه Python.

bash
# تنسيق ملف محلي
python -m json.tool config.json

# تمرير استجابة API عبر المُنسِّق
curl -s https://api.github.com/users/gvanrossum | python -m json.tool

# التنسيق من stdin
echo '{"service":"api-gateway","version":"2.1.0","healthy":true}' | python -m json.tool

# ترتيب المفاتيح أبجديًا
python -m json.tool --sort-keys data.json

# مسافة بادئة مخصصة (Python 3.9+)
python -m json.tool --indent 2 data.json
ملاحظة:أضاف Python 3.9 علامتَي --indent و --no-indent. لتصفية JSON أكثر قوة في الطرفية، فكر في jq — لكن python -m json.tool يُغطي حالة الاستخدام بالتنسيق دون أي تبعيات إضافية.

إذا لم تكن على الطرفية أصلاً — لصق استجابة من Postman أو ملف سجل — فإن JSON Formatter من ToolDeck يتيح لك اللصق والتنسيق والنسخ في خطوة واحدة، مع تمييز الصيغة والتحقق المدمجين.

المكتبات البديلة: orjson و rich

orjson — أسرع 5–10× مع دعم أصلي للأنواع

الوحدة القياسية json سريعة بما يكفي لمعظم حالات الاستخدام، لكن إذا كنت تُسلسل آلاف الكائنات في الثانية — خطوط أنابيب التسجيل، APIs عالية الإنتاجية، تصدير بيانات ضخمة — فإن orjson أسرع 5–10×. كما تتعامل أصليًا مع الأنواع التي لا تستطيع المكتبة القياسية تسلسلها بدون دالة default مخصصة: datetime، uuid.UUID، مصفوفات numpy، وdataclasses.

bash — تثبيت
pip install orjson
Python 3.8+
import orjson
from datetime import datetime, timezone
import uuid

event = {
    "event_id": uuid.uuid4(),                  # لا حاجة لـ str() — orjson يتعامل مع UUID
    "timestamp": datetime.now(timezone.utc),   # لا حاجة لـ isoformat()
    "service": "auth-service",
    "level": "INFO",
    "payload": {
        "user_id": "usr_9f3a2b",
        "action": "login",
        "ip": "192.168.1.42",
        "latency_ms": 34
    }
}

# orjson.dumps تُعيد bytes؛ .decode() تحوّله إلى str
print(orjson.dumps(event, option=orjson.OPT_INDENT_2).decode())
# {
#   "event_id": "a3f1c2d4-e5b6-7890-abcd-ef1234567890",
#   "timestamp": "2024-05-01T10:30:00+00:00",
#   "service": "auth-service",
#   ...
# }

شيئان مهمان: orjson.dumps() تُعيد bytes، وليس سلسلة نصية — استدعِ .decode() إذا احتجت سلسلة نصية. تدعم فقط مسافة بادئة من 2 مسافات عبر OPT_INDENT_2; للمخرجات بـ 4 مسافات استخدم json.dumps(indent=4) القياسية.

rich — تمييز الصياغة في الطرفية

إذا كنت تفحص JSON بانتظام في طرفية أو REPL، rich تُقدّم مخرجات ملونة بتمييز صياغي يجعل الهياكل المتداخلة بعمق مقروءة للوهلة الأولى. المفاتيح والسلاسل والأرقام والقيم المنطقية لكل منها لون مميز — أسهل بكثير للفحص من جدار نص أحادي اللون. إنها أداة للتصحيح فقط، وليست للتسلسل في الإنتاج.

bash — تثبيت
pip install rich
Python 3.8+
from rich import print_json
import json

# print_json() تقبل سلسلة JSON
raw = '{"event":"login","user_id":"usr_9f3a2b","timestamp":"2024-05-01T10:30:00Z","success":true,"meta":{"ip":"192.168.1.42","attempts":1}}'
print_json(raw)

# لطباعة قاموس Python بشكل منسق، حوّله إلى سلسلة أولًا
data = {
    "status": "success",
    "count": 42,
    "tags": ["python", "api", "backend"]
}
print_json(json.dumps(data))
تحذير:rich.print_json() تُخرج أكواد هروب ANSI للألوان في الطرفية — لا تلتقط هذه المخرجات أبدًا وتكتبها إلى ملف .json أو ترسلها كاستجابة API. استخدم json.dumps(indent=4) لأي مخرجات يقرأها الآلة.

simplejson — بديل متوافق مع المكتبة القياسية

simplejson هي المكتبة التي أصبحت الوحدة القياسية json في Python — لا تزال تُصان بشكل مستقل وتتقدم على المكتبة القياسية في الميزات الثانوية. إنها بديل مباشر حقيقي: غيّر الاستيراد وبقية كودك يبقى دون تغيير. مفيدة عندما تحتاج دعم Decimal بدون مُشفِّر مخصص، أو عند استهداف بيئات Python الأقدم.

bash — تثبيت
pip install simplejson
Python 3.8+
import simplejson as json  # API مطابق للمكتبة القياسية
from decimal import Decimal

order = {
    "item": "API subscription",
    "price": Decimal("49.99"),   # المكتبة القياسية ترمي TypeError هنا
    "quantity": 3,
}

# simplejson يُسلسل Decimal أصليًا — لا حاجة لـ default=
print(json.dumps(order, indent=4, use_decimal=True))
# {
#     "item": "API subscription",
#     "price": 49.99,
#     "quantity": 3
# }
ملاحظة:للأداء الخالص، orjson هو الخيار الأفضل. استخدم simplejson عندما تحتاج تسلسلDecimal أصليًا بدون كتابة مُشفِّر مخصص، أو عند صيانة قاعدة كود تستخدمه مسبقًا.

معالجة ملفات JSON الكبيرة دون نفاد الذاكرة

json.load() تقرأ الملف كاملًا في الذاكرة قبل أن تتمكن من الوصول إلى حقل واحد. في ملف يحتوي على ملايين السجلات أو حمولة تتجاوز الغيغابايت، هذا يتسبب في MemoryError — أو في أحسن الأحوال يجبر العملية على استخدام التبديل والزحف.

البث مع ijson

ijson محلل JSON تدفقي يُولّد العناصر واحدًا تلو الآخر من كائن ملف. تتكرر على عناصر المصفوفة دون الاحتفاظ بمجموعة البيانات الكاملة في الذاكرة — الذاكرة الأقصى تبقى متناسبة مع كائن واحد، لا حجم الملف.

bash — تثبيت
pip install ijson
Python 3.8+
import ijson
from decimal import Decimal

# events.json هيكله: {"events": [...ملايين الكائنات...]}
total_revenue = Decimal("0")
login_count = 0

with open("events.json", "rb") as f:   # ijson يتطلب الوضع الثنائي
    for event in ijson.items(f, "events.item"):
        if event.get("type") == "purchase":
            total_revenue += Decimal(str(event["amount_usd"]))
        elif event.get("type") == "login":
            login_count += 1

print(f"Revenue: ${total_revenue:.2f}  |  Logins: {login_count}")
# معالجة ملف 2 غيغابايت مع ~30 ميغابايت ذروة استخدام ذاكرة
ملاحظة:انتقل من json.load() إلى ijson عندما يتجاوز ملفك تقريبًا 50–100 ميغابايت. أقل من هذا الحد، json.load() أبسط وأسرع بكثير لأنه يستخدم محلل C-extension داخليًا. فوق 100 ميغابايت، مدخرات الذاكرة من البث تفوق التكلفة الإضافية.

NDJSON — كائن JSON واحد لكل سطر

NDJSON (JSON محدود بسطر جديد، يُسمى أيضًا JSON Lines أو .jsonl) يخزن كائن JSON كاملًا في كل سطر. مُصدِّرو السجلات ومستهلكو Kafka وخطوط أنابيب البيانات تُنتج هذا التنسيق كثيرًا لأن كل سطر يمكن إلحاقه وقراءته باستقلالية — لا حاجة لتحليل الملف كاملًا لإضافة سجل. المكتبة القياسية تتعامل معه بدون أي تبعيات إضافية.

Python 3.8+
import json
from pathlib import Path

# كتابة NDJSON — حدث واحد لكل سطر
events = [
    {"ts": "2024-05-01T10:00:00Z", "user": "usr_9f3a2b", "action": "login"},
    {"ts": "2024-05-01T10:01:03Z", "user": "usr_9f3a2b", "action": "purchase", "sku": "pro-plan"},
    {"ts": "2024-05-01T10:15:42Z", "user": "usr_4ab1d9", "action": "login"},
]

with open("events.ndjson", "w", encoding="utf-8") as f:
    for event in events:
        f.write(json.dumps(event, ensure_ascii=False) + "\n")

# قراءة NDJSON — ذاكرة ثابتة، بغض النظر عن حجم الملف
purchase_count = 0
with open("events.ndjson", "r", encoding="utf-8") as f:
    for line in f:
        line = line.strip()
        if not line:           # تخطي الأسطر الفارغة
            continue
        event = json.loads(line)
        if event.get("action") == "purchase":
            purchase_count += 1
            print(f"{event['ts']} — {event['user']} bought {event['sku']}")

الأخطاء الشائعة

رأيت هذه الأخطاء الأربعة في كل مراجعة كود تقريبًا تتعلق بتسلسل JSON — خاصةً من مطورين قادمين من JavaScript حيث تتعامل JSON.stringify مع الترميز تلقائيًا.

خطأ: استخدام print(data) بدلًا من json.dumps()

المشكلة: print() على قاموس يستخدم repr في Python — المخرجات تُظهر True/None (صياغة Python)، وليس true/null (صياغة JSON). ليس JSON صالحًا.

الحل: استخدم دائمًا json.dumps(data, indent=4) لمخرجات JSON صالحة ومقروءة.

After · Python
Before · Python
print(json.dumps(data, indent=4))
# {
#     "active": true,
#     "count": null
# }
data = {"active": True, "count": None}
print(data)
# {'active': True, 'count': None}
خطأ: نسيان ensure_ascii=False مع النصوص العربية

المشكلة: تُهرَّب الأحرف الخاصة (الأحرف العربية والأحرف المُعربة والرموز التعبيرية) إلى تسلسلات \\uXXXX، مما يجعل المخرجات غير مقروءة.

الحل: مرر ensure_ascii=False للحفاظ على أحرف Unicode الأصلية.

After · Python
Before · Python
json.dumps(user, indent=2, ensure_ascii=False)
# {"name": "فاطمة علي", "city": "القاهرة"}
user = {"name": "فاطمة علي", "city": "القاهرة"}
json.dumps(user, indent=2)
# {"name": "\u0641\u0627\u0637\u0645\u0629 \u0639\u0644\u064a", ...}
خطأ: استخدام json.dumps() للكتابة إلى ملف

المشكلة: json.dumps() تُعيد سلسلة نصية؛ ثم تحتاج إلى استدعاء f.write() منفصل، مما يُنشئ سلسلة نصية وسيطة غير ضرورية.

الحل: استخدم json.dump(data, f, indent=4) — تكتب مباشرة إلى كائن الملف.

After · Python
Before · Python
with open("out.json", "w", encoding="utf-8") as f:
    json.dump(data, f, indent=4, ensure_ascii=False)
with open("out.json", "w") as f:
    f.write(json.dumps(data, indent=4))
خطأ: الطباعة المنسقة مع pprint وتوقع JSON صالح

المشكلة: pprint.pprint() يستخدم صياغة Python (True، None، علامات اقتباس مفردة) التي تُرفضها محللات JSON.

الحل: استخدم json.dumps(indent=4) لأي مخرجات يجب أن تكون قابلة للتحليل كـ JSON.

After · Python
Before · Python
import json
print(json.dumps({"running": True, "last_error": None}, indent=4))
# {"running": true, "last_error": null}
import pprint
pprint.pprint({"running": True, "last_error": None})
# {'running': True, 'last_error': None}

مقارنة الأساليب — json.dumps، orjson، simplejson، rich

استخدم json.dumps() للتنسيق اليومي وكتابة الملفات — يُغطي 95% من حالات الاستخدام بدون أي تبعيات. الجأ إلى orjson عند التسلسل في مسار ساخن أو عندما تحتوي كائناتك على حقول datetime و UUID. استخدم simplejson عندما تحتاج توافقًا مباشرًا مع المكتبة القياسية مع دعم Decimal جاهز للاستخدام. احتفظ بـ rich.print_json() وpprint للفحص المحلي في الطرفية فقط — لا يُنتج أيٌّ منهما مخرجات يقرأها الآلة.

الطريقة
الإخراج
JSON صالح
السرعة
Non-ASCII
أنواع مخصصة
التثبيت
json.dumps(indent=4)
سلسلة نصية
معياري
ensure_ascii=False
default= / JSONEncoder
مدمج
json.dump(f, indent=4)
ملف
معياري
ensure_ascii=False
default= / JSONEncoder
مدمج
pprint.pprint()
repr Python
معياري
أصلي
✅ (أي repr)
مدمج
orjson.dumps(OPT_INDENT_2)
Bytes
أسرع 5–10×
أصلي
datetime, UUID, numpy
pip install orjson
python -m json.tool
stdout CLI
معياري
مدمج
simplejson.dumps()
سلسلة نصية
أسرع ~1.5×
ensure_ascii=False
Decimal أصلي
pip install simplejson
rich.print_json()
طرفية فقط
✅ (مدخل)
معياري
pip install rich

الأسئلة الشائعة

كيف أطبع JSON بشكل منسق في Python؟

استدعِ json.dumps(data, indent=4). يحدد المعامل indent عدد المسافات لكل مستوى تداخل. استورد وحدة json أولًا — فهي مضمنة في المكتبة القياسية لـ Python ولا تحتاج إلى pip install. مرر ensure_ascii=False إذا كانت بياناتك تحتوي على أحرف غير ASCII مثل الحروف المُعربة أو أحرف CJK أو الأحرف العربية.

python
import json

user = {"username": "ahmed_m", "plan": "enterprise", "permissions": ["read", "write", "deploy"]}
print(json.dumps(user, indent=4, ensure_ascii=False))

ما الفرق بين json.dumps() و json.dump()؟

json.dumps() (بحرف "s") تُعيد سلسلة نصية منسقة في الذاكرة. json.dump() (بدون "s") تكتب مباشرة إلى كائن ملف — مرر مقبض الملف المفتوح كوسيطة ثانية. لكتابة JSON منسق على القرص، يُعدّ json.dump(data, f, indent=4) النمط الاصطلاحي ويتجنب إنشاء سلسلة نصية وسيطة.

python
# dumps → سلسلة نصية في الذاكرة
formatted = json.dumps(data, indent=4)

# dump → كتابة مباشرة إلى الملف
with open('output.json', 'w', encoding='utf-8') as f:
    json.dump(data, f, indent=4)

لماذا يعرض json.dumps() تسلسلات \uXXXX بدلًا من الأحرف الفعلية؟

بشكل افتراضي، تهرب ensure_ascii=True كل حرف غير ASCII إلى تسلسل \uXXXX. اضبط ensure_ascii=False للحفاظ على أحرف Unicode الأصلية. هذا مهم بشكل خاص للأسماء العربية والعناوين وأي محتوى ينشئه المستخدمون.

python
data = {"city": "القاهرة", "greeting": "مرحباً"}

# افتراضي — مُهرَّب
json.dumps(data, indent=4)
# {"city": "\u0627\u0644\u0642\u0627\u0647\u0631\u0629", ...}

# مقروء
json.dumps(data, indent=4, ensure_ascii=False)
# {"city": "القاهرة", "greeting": "مرحباً"}

كيف أنسق سلسلة JSON نصية (وليس قاموسًا)؟

حلل السلسلة أولًا باستخدام json.loads()، ثم نسّقها باستخدام json.dumps(). يمكن تسلسل الاستدعاءين في سطر واحد للفحص السريع في الطرفية.

python
import json

raw = '{"endpoint":"/api/v2/users","timeout":30,"retry":true}'
print(json.dumps(json.loads(raw), indent=4))

هل يمكنني استخدام pprint لتنسيق JSON في Python؟

تُنتج pprint.pprint() تمثيل كائنات Python، وليس JSON صالحًا. فهي تستخدم True/False/None (صياغة Python) بدلًا من true/false/null (صياغة JSON). لا تمرر أبدًا مخرجات pprint إلى واجهة برمجية أو محلل JSON — استخدم json.dumps(indent=4) لأي مخرجات يجب أن تكون JSON صالحًا.

python
import pprint, json

data = {"active": True, "score": None}

pprint.pprint(data)     # {'active': True, 'score': None}  ← ليس JSON
json.dumps(data, indent=4)  # {"active": true, "score": null}  ← JSON صالح

كيف أرتب مفاتيح JSON أبجديًا في Python؟

أضف sort_keys=True إلى json.dumps(). من سطر الأوامر، استخدم python -m json.tool --sort-keys data.json. تجعل المفاتيح المرتبة فروق JSON مقروءة وتساعد في تحديد القيم المتغيرة بسرعة.

python
import json

server = {"workers": 4, "host": "0.0.0.0", "port": 8080, "debug": False}
print(json.dumps(server, indent=4, sort_keys=True))
# {
#     "debug": false,
#     "host": "0.0.0.0",
#     "port": 8080,
#     "workers": 4
# }

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

أدوات ذات صلة

متاح أيضاً بـ:GoJavaScriptBash
MS
Maria SantosBackend Developer

Maria is a backend developer specialising in Python and API integration. She has broad experience with data pipelines, serialisation formats, and building reliable server-side services. She is an active member of the Python community and enjoys writing practical, example-driven guides that help developers solve real problems without unnecessary theory.

DV
Dmitri Volkovالمراجع التقني

Dmitri is a DevOps engineer who relies on Python as his primary scripting and automation language. He builds internal tooling, CI/CD pipelines, and infrastructure automation scripts that run in production across distributed teams. He writes about the Python standard library, subprocess management, file processing, encoding utilities, and the practical shell-adjacent Python that DevOps engineers use every day.