يظهر خطأ JSONDecodeError في بايثون عندما تحاول json.load() أو json.loads() أو response.json() تحويل محتوى إلى JSON، لكن المحتوى فارغ أو ليس JSON صالحًا. ومن أشهر الرسائل:
Expecting value: line 1 column 1 (char 0).
إذا ظهر لك هذا الخطأ، لا تبدأ بتغيير الكود عشوائيًا. افحص أولًا المحتوى الذي تحاول فكّه: هل الملف أو النص فارغ؟ هل استجابة API أعادت HTML أو نصًا بدل JSON؟ هل توجد فاصلة زائدة أو علامات تنصيص مفردة؟ رسالة الخطأ نفسها تعطيك السطر والعمود والموقع الذي فشل عنده التحليل.
في هذا الدرس من سلسلة مشكلة وحل في بايثون سنشخّص أسباب JSONDecodeError ونصلح أشهر الحالات، سواء كان المصدر ملف JSON أو نصًا مع json.loads() أو استجابة HTTP.
الفكرة ببساطة:JSONDecodeErrorيعني أن محلل JSON لم يجد مستند JSON صالحًا في المحتوى الذي استلمه. وإذا كان الخطأ عندline 1 column 1 (char 0)فابدأ بفحص أن المحتوى ليس فارغًا وأنه JSON فعلًا. {alertInfo}
{getToc} $title={محتوى المقال}
أشهر رسائل JSONDecodeError وما تعنيه
| رسالة الخطأ | السبب المحتمل | ما الذي تفحصه أولًا؟ |
|---|---|---|
Expecting value: line 1 column 1 (char 0) |
محتوى فارغ، أو أول محرف ليس بداية JSON صالحة، أو استجابة HTML/نص بدل JSON. | اطبع المحتوى أو افحص حجم الملف واستجابة الخادم قبل التحليل. |
Expecting property name enclosed in double quotes |
مفتاح بدون علامات تنصيص مزدوجة، أو استخدام علامات مفردة، أو فاصلة زائدة في موضع معين. | راجع السطر والعمود المذكورين في الرسالة. |
Extra data |
يوجد أكثر من مستند JSON متتالٍ أو بيانات إضافية بعد انتهاء أول قيمة JSON. | تأكد أن الملف يحتوي على قيمة JSON واحدة، مثل object واحد أو list واحدة. |
القاعدة المهمة: لا تكتفِ باسم JSONDecodeError. اقرأ الجزء الذي يأتي بعده، لأن msg ورقم السطر والعمود يساعدانك على تحديد السبب بسرعة.
مثال كود يسبب JSONDecodeError
لنفترض أن لديك ملفًا اسمه data.json، وتريد قراءته:
import json
with open("data.json", "r", encoding="utf-8") as file:
data = json.load(file)
print(data)
إذا كان ملف data.json فارغًا، أو يحتوي على JSON غير صحيح، سيظهر خطأ JSONDecodeError.
ما معنى JSONDecodeError؟
كلمة Decode هنا تعني أن Python يحاول تفسير النص وتحويله من صيغة JSON إلى بيانات Python مثل dict أو list.
إذا كان النص مكتوبًا بطريقة صحيحة، يتم التحويل بنجاح. أما إذا كان النص فارغًا أو فيه خطأ في علامات التنصيص أو الفواصل أو الأقواس، فلن يستطيع Python قراءته، فيظهر خطأ JSONDecodeError.
مثال JSON صحيح:
{
"name": "Ali",
"age": 25
}
مثال JSON غير صحيح:
{
"name": "Ali",
"age": 25,
}
الخطأ هنا أن هناك فاصلة زائدة بعد آخر عنصر.
الفرق بين json.load و json.loads و response.json
نفس الخطأ قد يظهر من أكثر من مصدر، لذلك حدد أولًا ما الذي تحاول قراءته:
| الطريقة | تستخدم مع | مثال |
|---|---|---|
json.load(file) |
ملف مفتوح يحتوي على JSON. | json.load(file) |
json.loads(text) |
نص str أو بيانات نصية تحتوي على JSON. |
json.loads('{"name": "Ali"}') |
response.json() |
جسم استجابة HTTP عند استخدام مكتبة Requests. | response.json() |
إذا كنت تتعامل مع الملفات لأول مرة، راجع شرح مكتبة json في بايثون. الفرق المهم هنا أن json.load() يقرأ من كائن ملف، بينما json.loads() يحلل نصًا موجودًا بالفعل في الذاكرة.
أشهر أسباب JSONDecodeError
هذا الخطأ له أسباب كثيرة، لكن أكثرها شيوعًا عند المبتدئين:
- ملف JSON أو نص
json.loads()فارغ. - استجابة API فارغة، مثل
204 No Content. - الخادم أعاد HTML أو نصًا عاديًا بدل JSON.
- وجود فاصلة زائدة بعد آخر عنصر.
- استخدام علامات تنصيص مفردة بدل المزدوجة.
- نسيان قوس أو فاصلة.
- كتابة أكثر من JSON object في نفس الملف بدون قائمة.
- استخدام
json.loads()على نص غير صالح. - وجود تعليقات داخل ملف JSON.
السبب الأول: ملف أو نص JSON فارغ
من أكثر أسباب رسالة Expecting value: line 1 column 1 (char 0) أن يكون المحتوى فارغًا تمامًا أو يحتوي على مسافات فقط. يحدث ذلك مع ملف فارغ في json.load()، ومع نص فارغ في json.loads().
import json
json.loads("")
لا توجد قيمة JSON عند المحرف رقم 0، لذلك يفشل المحلل فورًا. الحل ليس إخفاء الاستثناء، بل معرفة لماذا أصبح المصدر فارغًا.
إذا كان الملف جديدًا ويجب أن يحتوي بنية افتراضية، فاكتب JSON صالحًا مثل:
{}
أو:
[]
أما إذا كان الملف يفترض أن يحتوي بيانات فعلية، فلا تستبدلها تلقائيًا بـ{} قبل معرفة سبب فقدان المحتوى.
إذا ظهر JSONDecodeError مع requests أو response.json()
قد يكون JSON نفسه صحيحًا في مشروعك، لكن الاستجابة القادمة من API ليست JSON أصلًا. هذه من أكثر الحالات المرتبطة برسالة Expecting value: line 1 column 1 (char 0).
قبل استدعاء response.json() افحص ثلاث نقاط:
status_code: هل أعاد الخادم حالة متوقعة؟Content-Type: هل الاستجابة معلّمة على أنها JSON؟response.textأوresponse.content: هل الجسم فارغ أو يحتوي HTML أو رسالة نصية؟
import requests
response = requests.get("https://example.com/api/data", timeout=10)
print(response.status_code)
print(response.headers.get("Content-Type"))
print(response.text[:200])
إذا وجدت صفحة HTML تبدأ مثلًا بـ <!DOCTYPE html> أو <html>، فالمشكلة ليست في محلل JSON؛ الخادم أعاد صفحة ويب أو صفحة خطأ بدل JSON.
حالة HTTP 204 No Content
الاستجابة ذات الحالة 204 تعني أن الخادم نجح لكنه لا يعيد جسمًا للمحتوى. لذلك استدعاء response.json() على جسم فارغ قد يسبب JSONDecodeError.
if response.status_code == 204 or not response.content.strip():
data = None
else:
data = response.json()
طريقة أكثر أمانًا عند قراءة JSON من API
import requests
response = requests.get("https://example.com/api/data", timeout=10)
response.raise_for_status()
content_type = response.headers.get("Content-Type", "").lower()
if response.status_code == 204 or not response.content.strip():
print("الاستجابة لا تحتوي على بيانات JSON.")
elif "json" not in content_type:
print("الاستجابة ليست معلّمة كـ JSON:", content_type)
print(response.text[:200])
else:
try:
data = response.json()
print(data)
except requests.exceptions.JSONDecodeError as error:
print("الاستجابة تبدو JSON حسب الترويسة، لكن محتواها غير صالح.")
print(error)
مهم: فحصContent-Typeإشارة مفيدة وليس ضمانًا مطلقًا. قد يرسل خادم ترويسة خاطئة، وقد يرسلapplication/jsonمع محتوى غير صالح. لذلك افحص أيضًا حالة الاستجابة والجسم نفسه عند التشخيص. {alertWarning}
السبب الثاني: استخدام علامات تنصيص مفردة
في Python يمكنك كتابة Dictionary بعلامات تنصيص مفردة أو مزدوجة، لكن في JSON يجب استخدام علامات تنصيص مزدوجة حول المفاتيح والنصوص.
هذا صحيح في Python كـ Dictionary:
{
'name': 'Ali',
'age': 25
}
لكنه غير صحيح كملف JSON. الصحيح في JSON:
{
"name": "Ali",
"age": 25
}
مهم: JSON ليس نفس Dictionary في Python تمامًا. قد يتشابهان في الشكل، لكن JSON له قواعد أكثر صرامة، وأهمها استخدام علامات التنصيص المزدوجة. {alertWarning}
السبب الثالث: وجود فاصلة زائدة
في JSON لا تضع فاصلة بعد آخر عنصر. هذا مثال خاطئ:
{
"name": "Ali",
"age": 25,
}
الصحيح:
{
"name": "Ali",
"age": 25
}
هذه الفاصلة الزائدة من أكثر الأخطاء التي تسبب JSONDecodeError.
السبب الرابع: كتابة تعليقات داخل JSON
في ملفات Python يمكنك كتابة تعليقات باستخدام #، لكن ملفات JSON لا تدعم التعليقات.
هذا JSON غير صحيح:
{
# اسم المستخدم
"name": "Ali"
}
الصحيح أن تحذف التعليق:
{
"name": "Ali"
}
إذا أردت وضع ملاحظات، اجعلها قيمة عادية داخل JSON:
{
"name": "Ali",
"note": "مستخدم تجريبي"
}
السبب الخامس: أكثر من كائن JSON في نفس الملف
لا يمكنك كتابة أكثر من كائن JSON منفصلين في نفس الملف بهذا الشكل:
{
"name": "Ali"
}
{
"name": "Sara"
}
قد يؤدي هذا إلى خطأ مثل:
JSONDecodeError: Extra data
الصحيح أن تضع البيانات داخل قائمة:
[
{
"name": "Ali"
},
{
"name": "Sara"
}
]
السبب السادس: استخدام True و False و None بدل صيغة JSON
في Python نستخدم True و False و None، لكن في JSON الصيغة تكون مختلفة:
| في Python | في JSON |
|---|---|
True |
true |
False |
false |
None |
null |
هذا JSON غير صحيح:
{
"active": True,
"deleted": None
}
الصحيح:
{
"active": true,
"deleted": null
}
إذا كتبت البيانات داخل Python كـ Dictionary ثم استخدمت json.dump، فسيحول Python القيم تلقائيًا إلى صيغة JSON الصحيحة.
طريقة حل JSONDecodeError خطوة بخطوة
عندما يظهر لك الخطأ، لا تغيّر الكود عشوائيًا. اتبع هذا الترتيب:
- اقرأ رسالة الخطأ كاملة، خصوصًا
Expecting valueأوExtra dataورقم السطر والعمود. - افحص المحتوى الذي يصل فعليًا إلى محلل JSON. إذا كنت تستخدم
json.loads()اطبع جزءًا من النص، وإذا كنت تستخدم API افحصstatus_codeوresponse.text. - إذا كان المصدر ملفًا، تأكد أنه موجود وليس فارغًا. ويمكنك مراجعة التعامل مع الملفات في بايثون إذا احتجت.
- تأكد أن المفاتيح والنصوص تستخدم علامات تنصيص مزدوجة وأن الأقواس والفواصل صحيحة.
- احذف الفاصلة الزائدة بعد آخر عنصر، ولا تضع تعليقات داخل JSON القياسي.
- تأكد أن المحتوى يمثل قيمة JSON واحدة فقط، مثل object واحد أو list واحدة.
- إذا كان المصدر API، لا تستدعِ
response.json()على استجابة204أو جسم فارغ. - استخدم أداة فحص JSON لتحديد موضع المشكلة بدل التخمين.
فحص ملف JSON من Terminal
تستطيع استخدام أداة json.tool المدمجة مع بايثون لفحص الملف مباشرة:
python -m json.tool data.json
إذا كان JSON صالحًا، ستعرض الأداة المحتوى بشكل منسق. وإذا كان غير صالح، ستظهر رسالة تحدد مكان الخطأ، وهذا مفيد قبل تعديل كود البرنامج نفسه.
استخدام try و except للتعامل مع الخطأ
إذا كان احتمال وجود JSON غير صالح واردًا، استخدم try وexcept للتعامل مع الخطأ بدون إيقاف البرنامج بالكامل. لكن تذكّر: التقاط الاستثناء لا يصلح JSON؛ هو فقط يمنحك فرصة لتسجيل المشكلة أو عرض رسالة أو استخدام قيمة بديلة.
import json
try:
with open("data.json", "r", encoding="utf-8") as file:
data = json.load(file)
print(data)
except json.JSONDecodeError as error:
print("صيغة JSON غير صحيحة.")
print("السبب:", error.msg)
print("السطر:", error.lineno)
print("العمود:", error.colno)
الخصائص msg وlineno وcolno مفيدة جدًا لأنها تخبرك برسالة الخطأ والمكان الذي توقف عنده محلل JSON. وإذا كنت تحتاج مراجعة أساسيات الاستثناءات، راجع شرح try وexcept في بايثون.
التعامل مع الملف الفارغ قبل json.load
إذا كنت تتوقع أن الملف قد يكون فارغًا، يمكنك قراءة النص أولًا والتأكد منه قبل تحويله إلى JSON.
import json
from pathlib import Path
file_path = Path("data.json")
if file_path.exists() and file_path.read_text(encoding="utf-8").strip():
data = json.loads(file_path.read_text(encoding="utf-8"))
print(data)
else:
print("الملف غير موجود أو فارغ.")
هذا الأسلوب مفيد عندما يكون الملف قد أُنشئ لكنه لا يحتوي على بيانات بعد.
إنشاء ملف JSON افتراضي إذا كان فارغًا
في بعض المشاريع، الأفضل أن تنشئ بيانات افتراضية إذا كان ملف JSON غير موجود أو فارغ. مثلًا ملف إعدادات:
import json
from pathlib import Path
file_path = Path("settings.json")
default_settings = {
"theme": "dark",
"language": "Arabic"
}
if not file_path.exists() or not file_path.read_text(encoding="utf-8").strip():
file_path.write_text(
json.dumps(default_settings, ensure_ascii=False, indent=4),
encoding="utf-8"
)
settings = json.loads(file_path.read_text(encoding="utf-8"))
print(settings)
هذا المثال يمنع البرنامج من محاولة قراءة ملف فارغ.
مقارنة بين JSON الصحيح والخاطئ
| الخطأ | غير صحيح | الصحيح |
|---|---|---|
| علامات تنصيص مفردة | {'name': 'Ali'} |
{"name": "Ali"} |
| فاصلة زائدة | {"name": "Ali",} |
{"name": "Ali"} |
| قيمة Python داخل JSON | {"active": True} |
{"active": true} |
| تعليق داخل JSON | {"name": "Ali" # comment} |
{"name": "Ali"} |
| أكثر من كائن منفصل | {...} {...} |
[{...}, {...}] |
أفضل ممارسات لتجنب JSONDecodeError
- استخدم
json.dumpوjson.dumpsلإنشاء JSON بدل كتابته يدويًا قدر الإمكان. - لا تضع فاصلة بعد آخر عنصر.
- استخدم علامات تنصيص مزدوجة في ملفات JSON.
- لا تكتب تعليقات داخل ملفات JSON.
- تأكد أن الملف ليس فارغًا قبل قراءته.
- استخدم
encoding="utf-8"عند التعامل مع العربية. - استخدم
try/exceptعند قراءة ملفات قد تكون غير صالحة. - ضع البيانات المتعددة داخل قائمة واحدة بدل عدة كائنات منفصلة.
مثال عملي كامل: قراءة JSON بأمان
هذا مثال يجمع بين فحص وجود الملف، فحص أنه ليس فارغًا، والتعامل مع خطأ JSONDecodeError.
import json
from pathlib import Path
file_path = Path("data.json")
if not file_path.exists():
print("الملف غير موجود.")
elif not file_path.read_text(encoding="utf-8").strip():
print("الملف فارغ.")
else:
try:
data = json.loads(file_path.read_text(encoding="utf-8"))
print(data)
except json.JSONDecodeError as error:
print("صيغة JSON غير صحيحة.")
print(error)
هذا الكود مناسب كبداية جيدة عندما تبني مشروعًا يقرأ بيانات من ملف JSON.
مصادر خارجية مفيدة للتوسع
- توثيق Python الرسمي لمكتبة json
- توثيق Python الرسمي لخطأ JSONDecodeError
- توثيق Requests لقراءة JSON من الاستجابة
الخلاصة
خطأ JSONDecodeError يظهر عندما يحاول محلل JSON قراءة محتوى غير صالح. قد يكون المصدر ملفًا فارغًا، نصًا فارغًا مع json.loads()، JSON مكتوبًا بطريقة خاطئة، أو استجابة API فارغة أو HTML بدل JSON.
ابدأ دائمًا من رسالة الخطأ نفسها ثم افحص المحتوى الفعلي قبل التحليل. إذا ظهر Expecting value: line 1 column 1 (char 0) فافحص أولًا أن المصدر غير فارغ وأن أول محتوى وصل إليك هو JSON فعلًا. واستخدم try/except للتعامل مع الخطأ، لا لإخفاء السبب.
الخلاصة العملية: لا تفترض أن المشكلة فيjson.load()أوjson.loads()نفسها. افحص الملف أو النص أو استجابة API التي وصلت إلى محلل JSON، ثم أصلح المصدر الذي جعل المحتوى فارغًا أو غير صالح. {alertSuccess}
أسئلة شائعة مع إجاباتها
ما معنى JSONDecodeError في Python؟
يعني أن Python حاول قراءة نص أو ملف كـ JSON، لكنه وجد أن التنسيق غير صحيح أو أن الملف فارغ.
ما سبب رسالة Expecting value؟
غالبًا تظهر عندما يكون ملف JSON فارغًا أو عندما لا يبدأ المحتوى بقيمة JSON صحيحة مثل كائن أو قائمة.
هل يمكن استخدام علامات تنصيص مفردة في JSON؟
لا. ملفات JSON تتطلب علامات تنصيص مزدوجة حول المفاتيح والنصوص.
هل JSON يدعم التعليقات؟
لا. JSON لا يدعم التعليقات، لذلك وجود تعليق داخل ملف JSON قد يسبب خطأ عند القراءة.
ما الفرق بين JSONDecodeError و FileNotFoundError؟
FileNotFoundError يعني أن الملف غير موجود أو أن المسار خطأ، أما JSONDecodeError فيعني أن المحتوى الذي وصل إلى محلل JSON غير صالح. إذا كانت المشكلة في المسار نفسه، راجع حل خطأ FileNotFoundError في بايثون.
كيف أتجنب JSONDecodeError؟
استخدم json.dump وjson.dumps لإنشاء JSON، وافحص أن المصدر غير فارغ، وتأكد من عدم وجود فاصلة زائدة أو علامات تنصيص مفردة أو تعليقات داخل JSON. وعند التعامل مع API افحص الاستجابة قبل استدعاء response.json().
ماذا يعني Expecting value: line 1 column 1 (char 0)؟
يعني أن محلل JSON فشل عند أول محرف تقريبًا. أكثر الأسباب شيوعًا: ملف أو نص فارغ، استجابة API بلا محتوى، أو محتوى يبدأ بـHTML أو نص عادي بدل JSON.
لماذا response.json() يسبب JSONDecodeError؟
يحدث ذلك عندما لا يحتوي جسم الاستجابة على JSON صالح. افحص status_code وContent-Type وresponse.text، وانتبه إلى حالة 204 No Content والاستجابات التي تعيد HTML بدل JSON.



