,JSON(JavaScript Object Notation) یک فرمت سبک و خوانا برای تبادل داده است که هم برای انسانها و هم برای ماشینها قابل خواندن و نوشتن است. مانند یک زبان مشترک بین برنامهها عمل میکند و به ویژه در ارتباطات وب (مثلاً وبسرویسها و APIها) بسیار کاربردی است. کلمه JSON مخفف عبارت JavaScript Object Notation است؛ گرچه این فرمت ریشه در زبان جاوااسکریپت دارد، اما اکنون مستقل از زبان بوده و در زبانهای مختلفی از جمله پایتون استفاده میشود. به دلیل سادگی ساختار و پشتیبانی زیاد، بسیاری از سیستمها و سرویسها برای ذخیرهسازی تنظیمات یا انتقال دادهها از JSON استفاده میکنند.
ساختار JSON به زبان ساده
در JSON ,دو ساختار اصلی وجود دارد: آبجکت و آرایه. یک آبجکت (object) با {} مشخص میشود و شامل جفتهای کلید و مقدار است؛ شبیه دیکشنری در پایتون. هر کلید (باید یک رشته باشد) و مقدار میتواند رشته، عدد، بولین (true/false)، null یا حتی یک آبجکت یا آرایهی دیگر باشد. یک آرایه (Array) با [] مشخص میشود و فهرستی مرتب از مقادیر را در بر میگیرد؛ مقادیر داخل آرایه با کاما جدا میشوند. جدول زیر نمونههایی از انواع دادههای JSON را با نماد (نمونه) نشان میدهد:
عنصر JSON | مثال |
آبجکت (Object) | { “name”: “Ali”, “age”: 30 } |
آرایه (Array) | [“apple”, 3, false] |
مقدار رشتهای | “سلام” |
مقدار عددی | 42 |
مقدار بولین | true / false |
مقدار تهی (Null) | null |
به طور خلاصه، یک نمونهی ساده از آبجکت JSON میتواند چنین باشد:
{
"name": "Ali",
"age": 25,
"languages": ["Python", "Java"]
}
در اینجا “name” یک کلید است و “Ali” مقدار آن (رشته)، “age” کلید دیگر با مقدار عددی ۲۵ و “languages” یک کلید با مقدار آرایهای از دو رشتهی “Python” و “Java” است. هر رشته در JSON باید داخل گیومهی دوتایی (“) نوشته شود و بین هر جفت کلید-مقدار یا هر مقدار از کاما استفاده میشود.
ماژول json در پایتون
پایتون یک بستهی داخلی به نام json دارد که برای کار با دادههای JSON استفاده میشود. به کمک این ماژول میتوان به راحتی بین ساختارهای پایتون (مثل دیکشنری و لیست) و فرمت JSON تبدیل انجام داد. توابع اصلی این ماژول عبارتند از:
تابع (json) | عملکرد |
json.dumps() | تبدیل شیء پایتون به رشتهی JSON |
json.dump() | نوشتن شیء پایتون به فایل JSON |
json.loads() | تبدیل رشتهی JSON به شیء پایتون |
json.load() | خواندن داده از فایل JSON به شیء پایتون |
این توابع کلیدی در عملیاتهای مختلف نقش دارند. در ادامه هر کدام را با مثال توضیح میدهیم.
تبدیل دیکشنری پایتون به رشته JSON
برای تبدیل یک دیکشنری (یا هر شیء پایتون قابل تبدیل) به رشتهی JSON، از تابع json.dumps() استفاده میکنیم. به این ترتیب دادههای پایتون به صورت یک رشته متنی در فرمت JSON درمیآیند. برای مثال:
import json
user = {
"username": "sara123",
"email": "sara@example.com",
"active": True,
"score": 42
}
json_str = json.dumps(user)
print(json_str)
در این مثال، دیکشنری user به رشتهی JSON تبدیل شده و در json_str ذخیره میشود. خروجی مشابه چنین متنی خواهد بود:
{"username": "sara123", "email": "sara@example.com", "active": true, "score": 42}
دقت کنید که مقادیر بولین در JSON با حروف کوچک (true یا false) نمایش داده میشوند و مقدار True پایتون به true در JSON تبدیل شده است. برای زیباسازی خروجی و اضافه کردن تورفتگی، میتوان از پارامتر indent در json.dumps() استفاده کرد تا رشته JSON با فرمت مرتب و قابل خواندنتری ایجاد شود.
تبدیل رشته JSON به دیکشنری پایتون
برای برعکس کردن روند بالا، یعنی تبدیل یک رشتهی JSON به ساختار پایتون، از تابع json.loads() استفاده میشود. به این صورت، اگر یک رشته JSON داشته باشیم که عموماً از فایل یا ورودی وب آمده، میتوانیم با loads آن را به دیکشنری یا لیست پایتون تبدیل کنیم. مثال:
json_data = '{"name": "Ali", "age": 25, "city": "Tehran"}'
data = json.loads(json_data)
print(data["city"])
در این مثال، json_data یک رشتهی JSON است. با اجرای json.loads(json_data) یک دیکشنری پایتون ایجاد میشود که مقدار کلید “city” برابر “Tehran” است. پس از تبدیل میتوان به عناصر دیکشنری دسترسی داشت و از آن مانند هر دیکشنری عادی پایتون استفاده کرد.
فایل JSON چیست؟
گاهی نیاز داریم دادههای پایتون را در یک فایل ذخیره کنیم تا در آینده قابل استفاده باشد، مانند ذخیره تنظیمات برنامه یا اطلاعات کاربر. برای این کار از تابع json.dump() استفاده میکنیم. ابتدا فایل را با حالت نوشتن (“w”) باز میکنیم(نوشتن در فایل JSON) و سپس دیکشنری پایتون را در آن مینویسیم. به عنوان مثال فرض کنید بخواهیم تنظیمات برنامه را ذخیره کنیم :
import json
settings = {
"theme": "dark",
"font_size": 14,
"show_line_numbers": False
}
with open("settings.json", mode="w", encoding="utf-8") as f:
json.dump(settings, f)
در اینجا یک فایل به نام settings.json ایجاد شده و دیکشنری settings با فرمت JSON داخل آن ذخیره میشود. توجه کنید که برای اطمینان از درستی کاراکترها، اغلب از رمزگذاری UTF-8 استفاده میشود. پس از اجرای این کد، فایل settings.json شامل چیزی شبیه به زیر خواهد بود:
{"theme": "dark", "font_size": 14, "show_line_numbers": false}
در این حالت، JSON مستقیماً در فایل نوشته میشود.
خواندن فایل JSON در پایتون
برای خواندن دادهها از یک فایل JSON و تبدیل آن به ساختار پایتون، از تابع json.load() استفاده میشود. کافی است فایل JSON را باز کرده و به json.load() بدهیم. به عنوان مثال فرض کنید میخواهیم تنظیمات برنامهای که در بخش قبل ذخیره کردیم را بارگذاری کنیم:
with open("settings.json", encoding="utf-8") as f:
settings = json.load(f)
print(settings["theme"]) # نمایش "dark"
کاربرد json در پایتون
چند مثال واقعی از کاربرد JSON در پایتون را ببینیم:- ذخیره اطلاعات کاربر: فرض کنید یک فرم ثبتنام داریم که اطلاعات نام، ایمیل و امتیاز کاربر را دریافت میکند. میتوانیم این اطلاعات را در یک دیکشنری پایتون جمعآوری کرده و با json.dump() در فایلی مثل user.json ذخیره کنیم تا بعداً قابل بازیابی باشد.
- تنظیمات برنامه: بسیاری از برنامهها برای ذخیره تنظیمات (پس زمینه، اندازه قلم، زبان و…) از فایلهای JSON استفاده میکنند. با ترکیب json.dump() و json.load() میتوان تنظیمات را بین اجراهای برنامه حفظ کرد.
- ارسال داده به API: در یک مثال شبکه، ممکن است بخواهیم دادهای را به یک سرویس خارجی ارسال کنیم (مانند فراخوانی یک API). در این صورت، معمولاً دیکشنری پایتون را با json.dumps() به رشته JSON تبدیل کرده و به عنوان بدنهی درخواست HTTP ارسال میکنیم.
مشکلات رایج هنگام کار با JSON در پایتون
در حین کار با JSON ممکن است با چند مشکل متداول روبهرو شویم. در ادامه برخی از آنها را میبینیم و راهحل ساده ارائه میدهیم:
خطای JSONDecodeError (شکست در تبدیل JSON): اگر رشته یا فایل JSON دارای syntax نامعتبر باشد (مثلاً ویرگول اضافی یا گیومه اشتباه)، تابع json.load() یا json.loads() خطا میدهد. برای مثال استفاده از {‘name’: ‘Ali’} با گیومهی تکی باعث خطا میشود. راهحل: دقت کنید در JSON حتماً برای کلیدها و رشتهها از گیومهی دوتایی استفاده شود و هیچ ویرگول اضافی در انتهای آرایه یا آبجکت قرار نگیرد.
در این نمونه میبینید که فقط یک اشتباه ظاهراً کوچک – گیومهٔ تکی یا ویرگول اضافی – کافی است تا json.loads() یا json.load() به JSONDecodeError برخورد کند. هر دو مثال زیر عمداً نادرست نوشته شدهاند تا خطا را ببینی؛ سپس نسخهٔ درستشان و دلیل خطا توضیح داده میشود.
مثال ۱ – گیومهٔ تکی بهجای دوتایی
import json
bad_json = "{'name': 'Ali'}" # ❌ گیومهٔ تکی در کلید و مقدار
data = json.loads(bad_json) # ← JSONDecodeError
خروجی کنسول:
json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
علت: طبق استاندارد JSON، تمام رشتهها (چه کلید- چه مقدار) باید با گیومهٔ دوتایی " نوشته شوند؛ گیومهٔ تکی در JSON معنایی ندارد و خطای بالا را ایجاد میکند
اصلاح درست:
good_json = '{"name": "Ali"}'
print(json.loads(good_json)) # {'name': 'Ali'}
مثال ۲ – ویرگول اضافی در آخر در object
import json
bad_json = """
{
"name": "Sara",
}
""" # ❌ کامای اضافی بعد از "Sara"
json.loads(bad_json) # ← JSONDecodeError
خطا:
json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 4 column 1 (char 26)
علت: در JSON آخرین جفت «کلید–مقدار» نباید ویرگول پایانی داشته باشد؛ وجود کاما باعث میشود تجزیهگر انتظار یک کلید دیگر داشته باشد و خطا دهد.
اصلاح درست:
good_json = """
{
"name": "Sara"
}
"""
print(json.loads(good_json)) # {'name': 'Sara'}
کلیدهای نامعتبر: در دیکشنری پایتون میتوان از انواع متغیر به عنوان کلید استفاده کرد، اما در JSON کلیدها فقط باید از نوع رشته یا اعداد یا بولین (true/false) یا null باشند. برای مثال اگر یک تاپل یا لیست را به عنوان کلید یک دیکشنری استفاده کنید و بخواهید آن را با json.dumps() تبدیل کنید، با خطای TypeError: keys must be str, int, float, bool or None مواجه خواهید شد. راهحل: کلیدهای دیکشنری را به رشته تبدیل کنید یا از پارامتر skipkeys=True در json.dumps() استفاده کنید تا کلیدهای نامعتبر نادیده گرفته شوند.
در کُدهای زیر میبینید وقتی یک دیکشنری با کلید «نامعتبر» (تاپل یا لیست) را با json.dumps() تبدیل کنیم، پایتون خطای TypeError میدهد؛ بعد سه راه ساده برای رفع مشکل را نشان میدهم.
1) خود خطا را ببینیم
import json
bad_dict = {('x', 'y'): 1, [1, 2]: "oops"} # کلیدِ تاپل و لیست
json_str = json.dumps(bad_dict) # ← خطا!
خروجی ترمینال:
TypeError: keys must be str, int, float, bool or None, not tuple
2) راهحل یک ـ تبدیل کلیدها به رشته
fixed_dict = {str(k): v for k, v in bad_dict.items()}
json_str = json.dumps(fixed_dict)
print(json_str) # {"('x', 'y')": 1, '[1, 2]': "oops"}
با یک comprehension ساده کلیدها را به str تبدیل کردیم و سپس بدون خطا سریال شد. این روش زمانی خوب است که واقعاً به همهٔ کلیدها نیاز داریم.
3) راهحل دو ـ نادیدهگرفتن کلیدهای بد با skipkeys=True
json_str = json.dumps(bad_dict, skipkeys=True)
print(json_str) # {"('x', 'y')": 1}
وقتی پارامتر skipkeys را True بدهیم، هر کلیدی که از نوع مجاز نیست حذف میشود و بهجای خطا کلاً نادیده گرفته میشود
توجه: شاید دادهای از دست برود؛ این روش برای گزارش یا لاگ بیاهمیت مناسب است، نه برای اطلاعات حیاتی.
4) راهحل سه ـ ساخت دیکشنری جدید با کلیدهای مجاز گزینشی
clean_dict = {}
for k, v in bad_dict.items():
if isinstance(k, (str, int, float, bool, type(None))):
clean_dict[k] = v
json_str = json.dumps(clean_dict)
print(json_str) # { "('x', 'y')": 1 }
این روش رایج تر است ولی کنترل کامل میدهد؛ مثلاً میتوانیم تنها کلیدهای بولی یا عددی را نگه داریم.
مقادیر غیرقابل تبدیل: برخی از انواع داده پایتون مثل اشیاء (object) دلخواه، تاریخ و زمان (datetime)، مجموعهها (set) و … به طور پیشفرض قابل تبدیل به JSON نیستند و باعث خطای TypeError: … is not JSON serializable میشوند. برای حل این مشکل میتوان ابتدا این دادهها را به انواع پایه (مثلاً لیست یا دیکشنری) تبدیل کرد یا یک کلاس رمزگذار (JSONEncoder) سفارشی نوشت. در سادهترین حالت، مثلاً برای یک set میتوان از تابع list() استفاده کرده و آن را به لیست تبدیل کرد.
با رعایت این نکات و استفاده صحیح از توابع ماژول json، میتوانید به راحتی از فرمت JSON در برنامههای پایتون خود استفاده کنید و دادهها را تبادل یا ذخیره کنید.
منابع:







