آنچه در این مقاله میخوانید
نحوه چاپ راحت و خوانای JSON در پایتون (از پایه تا پیشرفته)
۲۴ مهر ۱۴۰۴
فرمت JSON (JavaScript Object Notation) یکی از پرکاربردترین استانداردها برای تبادل داده در وب است. به خاطر ساختار ساده و خوانایی بالایی که دارد، تقریبا در همهجا از آن استفاده میشود. مانند config files یا ارسال و دریافت داده بین APIها.
البته، JSON همیشه به همین سادگی هم نخواهد بود! معمولا دادهها در قالب فشرده و در یک خط ذخیره یا ارسال میشوند تا فضای کمتری بگیرند. این حالت برای ماشینها عالی است، اما برای توسعهدهندگان، خواندن و ویرایش آن سخت میشود. در این مقاله از وبلاگ لیارا قرار است به این مطلب بپردازیم. ابتدا با مبانی کار JSON در پایتون و ماژول داخلی json آشنا خواهیم شد، سپس به سراغ چالشهای پیشرفتهتر خواهیم رفت. در نهایت، از کتابخانههای سریعتر و بهینهتر برای افزایش سرعت برنامه استفاده خواهیم کرد.
همین الان، بدون هیچگونه پیچیدگی، هاست Python خود را در کمتر از ۳۰ ثانیه راهاندازی کنید.
✅ استقرار سریع و آسان ✅ پشتیبانی از فریمورکهای مختلف ✅ عملکرد پایدار
خرید هاست Python
آنچه در ادامه خواهید خواند:
- نکات کلیدی
- فرمتبندی رشته JSON در پایتون
- فرمتبندی فایل JSON در پایتون
- پارامترهای پیشرفته تابع
json.dumps() - پردازش فایلهای JSON بزرگ
- کتابخانههای جایگزین برای JSON
- کار با اشیای سفارشی
- اشکالزدایی پاسخهای API
- ثبت دادههای ساختاریافته
- بهبود خوانایی فایلهای تنظیمات
نکات کلیدی
- از پارامترهای
indentوsort_keysدر تابعjson.dumps()برای داشتن خروجی JSON خوانا و ساختارمند استفاده کنید. - با استفاده از پارامترهای
separatorsوensure_ascii، فشردگی و کدگذاری کاراکترهای خروجی JSON را کنترل کنید. - برای سریالسازی اشیای سفارشی پایتون که بهصورت پیشفرض توسط JSON پشتیبانی نمیشوند، از یک زیرکلاس
JSONEncoderیا تابع هندلر در پارامترdefaultاستفاده کنید. - فایلهای JSON بزرگ را با استفاده از پارسرهای جریانمحور مانند
ijsonیا فرمت JSON خطی (Line-Delimited JSON) بدون فشار بر حافظه پردازش کنید. - برای برنامههای دادهمحور، با جایگزینی ماژول استاندارد
jsonبا کتابخانههایی مانندorjsonعملکرد را بهبود دهید. - با استفاده از پارامتر
object_hookدر تابعjson.loads()، اشیای سفارشی پایتون را بازسازی کنید. - تجربه اشکالزدایی را با استفاده از کتابخانه
richبرای چاپ زیبای JSON با برجستهسازی نحوی در ترمینال بهبود دهید.

فرمت بندی رشته JSON در پایتون
برای یک رشته JSON با فرمت زیبا، میتوان از تابع json.dumps() استفاده کرد. بهعنوان مثال، فرض کنید یک رشته JSON خام حاوی اطلاعات کارمندان را در اختیار داریم:
import json
json_data = '[{"ID":10,"Name":"Pankaj","Role":"CEO"},' \
'{"ID":20,"Name":"David Lee","Role":"Editor"}]'
json_object = json.loads(json_data)
json_formatted_str = json.dumps(json_object, indent=2)
print(json_formatted_str)
خروجی این کد بهصورت زیر خواهد بود، به آن دقت کنید.
[
{
"ID": 10,
"Name": "Pankaj",
"Role": "CEO"
},
{
"ID": 20,
"Name": "David Lee",
"Role": "Editor"
}
]
ابتدا با استفاده از json.loads()، رشته JSON به یک شیء پایتون تبدیل میشود. سپس تابع json.dumps() این شیء را به یک رشته JSON با فرمت زیبا تبدیل میکند. پارامتر indent سطح (فاصلهگذاری) را برای خروجی تعیین میکند.
فرمت بندی فایل JSON در پایتون
حال فرض کنید میخواهیم دادههای یک فایل JSON را چاپ کنیم. اگر فایل از قبل بهصورت فرمتشده ذخیره شده باشد، چه اتفاقی میافتد؟ بیایید این موضوع را کامل بررسی کنیم.
فرض کنید فایلی به نام Cars.json با محتوای زیر را در اختیار داریم:
import json
json_data = '[{"ID":10,"Name":"Pankaj","Role":"CEO"},' \
'{"ID":20,"Name":"David Lee","Role":"Editor"}]'
json_object = json.loads(json_data)
json_formatted_str = json.dumps(json_object, indent=2)
print(json_formatted_str)
کد زیر را اجرا خواهیم کرد:
[
{
"ID": 10,
"Name": "Pankaj",
"Role": "CEO"
},
{
"ID": 20,
"Name": "David Lee",
"Role": "Editor"
}
]
پارامترهای پیشرفته تابع json.dumps()
پارامترهای indent و sort_keys برای ساخت JSON خوانا بسیار کاربردی خواهد بود، اما تابع json.dumps() قابلیتهای پیشرفتهتری نیز ارائه میدهد که امکان کنترل دقیقتر فرآیند سریالسازی را فراهم میکنند. در ادامه، برخی از مهمترین این پارامترها بررسی میشوند.
separators: کنترل فضای سفید برای خروجی فشرده
پارامتر separators برای شما این بستر را به وجود میآورد تا کاراکترهای جداکننده در خروجی JSON را سفارشی سازی کنید. این پارامتر یک تاپل شامل دو رشته را میپذیرد: (item_separator, key_separator)، که بهترتیب جداکننده آیتمها و جداکننده کلید-مقدار را مشخص میکنند. بهصورت پیشفرض، پایتون از (“, ”, “: ”) استفاده میکند، که شامل یک فاصله پس از کاما و کولون برای خوانایی بهتر است.
برای تولید خروجی فشردهتر، میتوانید این فاصلهها را حذف کنید. این روش زمانی کاربردی است که اندازه فایل اهمیت داشته باشد و خوانایی در اولویت نباشد.
مانند: برای درک بهتر یک دیکشنری را در ادامه خواهیم ساخت.
import json
data = {
"name": "John Doe",
"age": 30,
"isStudent": False,
"courses": [
{"title": "History", "credits": 3},
{"title": "Math", "credits": 4}
]
}
حال آن را با جداکنندههای پیشفرض و نسخهای فشردهتر سریالسازی خواهیم کرد:
print(json.dumps(data, indent=4))
print(json.dumps(data, indent=4, separators=(',', ':')))
خروجی که نشان میدهد شامل اطلاعات زیر خواهد بود.
{
"name": "John Doe",
"age": 30,
"isStudent": false,
"courses": [
{
"title": "History",
"credits": 3
},
{
"title": "Math",
"credits": 4
}
]
}
فشرده با separators:
{
"name":"John Doe",
"age":30,
"isStudent":false,
"courses":[
{
"title":"History",
"credits":3
},
{
"title":"Math",
"credits":4
}
]
}
در نسخه دوم، فاصلههای پس از کولونها حذف شدهاند و خروجی کمی کوچکتر خواهد بود.
ensure_ascii: کار با کاراکترهای غیرلاتین
بهصورت پیشفرض، تابع json.dumps() تمام کاراکترهای غیر-ASCII را بهصورت کدهای فرار (escape codes) مانند \u00e9 برای کاراکتر ‘é’ تبدیل میکند. این رفتار سازگاری را تضمین میکند، اما در کار با زبانهای غیرانگلیسی میتواند خوانایی JSON را کاهش دهد.
با تنظیم ensure_ascii=False، میتوانید دستور دهید که کاراکترهای غیر-ASCII مستقیما نوشته شوند. این گزینه برای سیستمهایی که از UTF-8 پشتیبانی میکنند توصیه میشود.
به عنوان مثال با کاراکترهای غیر-ASCII:
import json
data = {"name": "Søren", "city": "København"}
print(json.dumps(data))
print(json.dumps(data, ensure_ascii=False))
خروجی که مشاهده خواهید کرد به صورت زیر خواهد بود.
{"name": "S\u00f8ren", "city": "K\u00f8benhavn"}
{"name": "Søren", "city": "København"}
خروجی دوم خواناتر است و برای سیستمهای سازگار با UTF-8 مناسبتر است.
default: مدیریت اشیای سفارشی پایتون
اگر بخواهید یک شیء پایتون مانند datetime یا یک کلاس سفارشی را سریالسازی کنید که بهصورت پیشفرض توسط JSON پشتیبانی نمیشود، با خطای TypeError مواجه خواهید شد. پارامتر default راهحلی مناسب برای این مشکل خواهد بود.
میتوانید تابعی را به default بدهید که برای هر شیء غیرقابل سریالسازی فراخوانی شود. این تابع باید نسخهای قابل سریالسازی از شیء را بازگرداند.
برای درک بهتر به مثال زیر توجه کنید: سریالسازی یک شیء datetime و یک کلاس سفارشی User:
import json
from datetime import datetime
class User:
def __init__(self, name, registered_at):
self.name = name
self.registered_at = registered_at
def custom_serializer(obj):
if isinstance(obj, datetime):
return obj.isoformat()
if isinstance(obj, User):
return {
"name": obj.name,
"registered_at": obj.registered_at.isoformat(),
"__class__": "User"
}
raise TypeError(f"شیء از نوع {type(obj).__name__} قابل سریالسازی به JSON نیست")
user = User("Jane Doe", datetime.now())
json_string = json.dumps(user, default=custom_serializer, indent=4)
print(json_string)
خروجی به صورت زیر خواهد بود.
{
"name": "Jane Doe",
"registered_at": "2025-09-11T15:03:18.673824",
"__class__": "User"
}
این روش امکان تعریف متمرکز منطق سریالسازی برای انواع سفارشی را فراهم میکند و کد را بهتر و قابل نگهداریتر میسازد.
پردازش فایلهای JSON بزرگ
هنگام کار با بیگ دیتاها، ممکن است با فایلهای JSON مواجه شوید که برای بارگذاری کامل در حافظه بیش از حد بزرگ هستند. استفاده از json.load() در چنین مواردی منجر به خطای MemoryError میشود. خوشبختانه، تکنیکهایی برای پردازش این فایلها بدون مصرف حافظه زیاد وجود دارد. که در ادامه برای شما شرح خواهیم داد.

پارسرهای جریانمحور: ijson
پارسرهای جریانمحور بهجای آنکه کل سند را یکجا بارگذاری کنند، فایل را بهصورت تدریجی و قطعهقطعه میخوانند و تجزیه میکنند. این روش پردازش فایلهای بسیار بزرگ را با مصرف حافظه ثابت و کم را به ارمغان خواهد آورد.
کتابخانه ijson یکی از ابزارهای محبوب برای این منظور در پایتون است. این کتابخانه جریان JSON را تجزیه کرده و آیتمها را بهمحض یافتن yield میکند.
برای این عمل ابتدا کتابخانه را نصب کنید:
pip install ijson
فرض کنید فایل large_data.json شامل آرایهای از اشیای کاربر است:
[
{"id": 1, "name": "Alice", "data": "..."},
{"id": 2, "name": "Bob", "data": "..."},
...
]
بهجای بارگذاری کل لیست، میتوانید با ijson آن را بهصورت تدریجی پردازش کنید:
import ijson
filename = "large_data.json"
with open(filename, 'r') as f:
users = ijson.items(f, 'item')
for user in users:
print(f"پردازش کاربر: {user['name']}")
در این مثال، ijson.items(f, 'item') یک ژنراتور ایجاد میکند که هر شیء از آرایه ریشه را yield میکند. در هر لحظه تنها یک شیء کاربر در حافظه نگه داشته میشود، که برای بیگ دیتاها از آن استفاده میشود.
JSON خطی (NDJSON)
فرمت JSON خطی (Newline Delimited JSON یا NDJSON) روش دیگری برای مدیریت دادههای بزرگ است. در این فرمت، هر خط از فایل یک شیء JSON کامل و معتبر است.
مثال فایل data.ndjson:
{"id": 1, "event": "login", "timestamp": "2025-09-11T10:00:00Z"}
{"id": 2, "event": "click", "target": "button_a", "timestamp": "2025-09-11T10:01:15Z"}
{"id": 1, "event": "logout", "timestamp": "2025-09-11T10:05:30Z"}
این فرمت برای پردازش جریانمحور مناسب است، زیرا میتوانید فایل را خط به خط پردازش کنید. هر خط بهصورت مستقل تجزیه میشود.
پردازش فایل NDJSON در پایتون:
import json
filename = "data.ndjson"
with open(filename, 'r') as f:
for line in f:
try:
event_data = json.loads(line)
print(f"پردازش رویداد: {event_data['event']} برای کاربر {event_data['id']}")
except json.JSONDecodeError:
print(f"خط نادرست رد شد: {line.strip()}")
کتابخانههای جایگزین برای JSON
ماژول داخلی json پایتون برای بسیاری از کاربردها کافی خواهد بود، اما کتابخانههای ثالث میتوانند عملکرد بهتر و ویژگیهای بیشتری را ارائه دهند.
| کتابخانه | ویژگیهای کلیدی | بهترین کاربردها |
|---|---|---|
orjson | عملکرد بسیار بالا، پشتیبانی از انواع اضافی (مانند datetime و dataclasses)، خروجی باینری فشرده UTF-8. | برنامههای حساس به عملکرد، APIهای وب. |
simplejson | کتابخانهای که ماژول json بر اساس آن ساخته شده، گاهی سریعتر و با ویژگیهای جدیدتر. | جایگزین مستقیم برای json با بهبود عملکرد. |
rich | چاپ زیبای JSON با برجستهسازی نحوی در ترمینال، نه یک پارسر. | بهبود خوانایی و اشکالزدایی در توسعه. |
orjson: انتخابی برای عملکرد بالا
کتابخانه orjson یک کتابخانه JSON سریع است که از ماژول استاندارد json عملکرد بهتری دارد. این کتابخانه در زبان Rust نوشته شده و برای سرعت بالا طراحی شده است.
برای نصب بایستی:
pip install orjson
استفاده از orjson مشابه ماژول داخلی است، اما در حالت پیشفرض خروجی را بهصورت bytes تولید میکند.
import orjson
from datetime import datetime
data = {
"name": "Project X",
"deadline": datetime(2026, 1, 1),
"status": "active"
}
json_bytes = orjson.dumps(data)
print(json_bytes)
print(orjson.loads(json_bytes))
خروجی باید به صورت زیر نمایش داده شود.
b'{"name":"Project X","deadline":"2026-01-01T00:00:00+00:00","status":"active"}'
{'name': 'Project X', 'deadline': '2026-01-01T00:00:00+00:00', 'status': 'active'}
simplejson: جایگزینی با ویژگیهای غنی
کتابخانه simplejson همان کتابخانهای است که ماژول json پایتون بر اساس آن توسعه یافته است. این کتابخانه همچنان فعالانه توسعه داده میشود و گاهی ویژگیها یا بهینهسازیهای جدیدی را پیش از ماژول استاندارد ارائه میدهد.
برای نصب آن بایستی:
pip install simplejson
استفاده از آن مشابه ماژول json است و میتواند بهعنوان جایگزین مستقیم استفاده شود:
import simplejson as json
data = {"key": "value"}
print(json.dumps(data))
rich: برای خروجی زیبای ترمینال
هنگام اشکالزدایی یا بررسی دادههای JSON در ترمینال، خوانایی اهمیت زیادی دارد. کتابخانه rich امکان چاپ زیبای دادهها با برجستهسازی نحوی را به ارمغان میآورد و برای ساختارهای پیچیده ساخته شده است.
برای آنکه بتوانید آن را نصب کنید:
pip install rich
برای چاپ زیبای JSON با rich:
import json
from rich.console import Console
data = {
"name": "John Doe",
"age": 30,
"isStudent": False,
"courses": [
{"title": "History", "credits": 3},
{"title": "Math", "credits": 4}
]
}
console = Console()
json_string = json.dumps(data)
console.print_json(json_string)
این کد خروجی رنگی و تورفتهای در ترمینال خواهد ساخت که خواندن ساختارهای تو در تو را آسانتر میکند.
کار با اشیای سفارشی
پیشتر مشاهده کردیم که پارامتر default در json.dumps() چگونه برای سریالسازی اشیای سفارشی استفاده میشود. برای سناریوهای پیچیدهتر، خصوصا زمانی که نیاز به دیسریالسازی سفارشی دارید، ساخت کلاسهای انکودر و دیکودر سفارشی عملکردی ساختارمند و شیءگرا را خواهد داشت.
JSONEncoder سفارشی
با ساخت یک زیرکلاس از json.JSONEncoder و بازنویسی متد default()، میتوانید انکودری قابل استفاده مجدد برای اشیای سفارشی بسازید. این روش منطق سریالسازی را در یک کلاس محصور میکند، که برای پروژههای با چندین نوع سفارشی مناسبتر است.
به عنوان مثال:
import json
from datetime import datetime
class User:
def __init__(self, name, registered_at):
self.name = name
self.registered_at = registered_at
class CustomEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime):
return obj.isoformat()
if isinstance(obj, User):
return {
"name": obj.name,
"registered_at": obj.registered_at.isoformat(),
"__class__": "User"
}
return super().default(obj)
user = User("Jane Doe", datetime.now())
json_string = json.dumps(user, cls=CustomEncoder, indent=4)
print(json_string)
این کد همان خروجی قبلی را تولید میکند، اما منطق در کلاس CustomEncoder است.
JSONDecoder سفارشی
دیسریالسازی فرآیند تبدیل یک رشته JSON به شیء پایتون است. برای بازسازی اشیای سفارشی، میتوانید از پارامتر object_hook در json.loads() استفاده کنید. این پارامتر تابعی را مشخص میکند که برای هر دیکشنری دیکودشده فراخوانی میشود و میتواند آن را به شیء دیگری تبدیل کند.
برای مثال با استفاده از کلید __class__ برای بازسازی شیء User میتواند:
import json
from datetime import datetime
def from_json_object(dct):
if "__class__" in dct and dct["__class__"] == "User":
return User(name=dct["name"], registered_at=datetime.fromisoformat(dct["registered_at"]))
return dct
json_string = """
{
"name": "Jane Doe",
"registered_at": "2025-09-11T15:03:18.673824",
"__class__": "User"
}
"""
user_object = json.loads(json_string, object_hook=from_json_object)
print(type(user_object))
print(user_object.name)
print(user_object.registered_at)
خروجی قابل مشاهده به صورت زیر خواهد بود.
<class '__main__.User'>
Jane Doe
2025-09-11 15:03:18.673824
این عمل نشان میدهد که object_hook چگونه دیکشنری را به یک نمونه از کلاس User تبدیل کرده است.
اشکال زدایی پاسخهای API
پاسخهای API در بیشتر مواقع به صورت یک خط طولانی JSON برای کاهش پهنای باند ارائه میشوند. این فرمت برای انسان خواندنش دشوار است، به خصوص برای دادههای پیچیده یا تو در تو. فرمتبندی زیبا، این رشته را به ساختاری خوانا و تورفته تبدیل میکند و شناسایی دادهها، فیلدهای گمشده یا خطاها را آسانتر میکند.
به عنوان مثال با استفاده از API آزمایشی JSONPlaceholder:
import requests
import json
url = "https://jsonplaceholder.typicode.com/posts/1"
response = requests.get(url)
if response.status_code == 200:
data = response.json()
print(json.dumps(data))
print(json.dumps(data, indent=2))
else:
print(f"خطا: کد وضعیت {response.status_code}")
خروجی که مشاهده میکنید به صورت زیر خواهد بود.
{"userId": 1, "id": 1, "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"}
{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
}
نسخه فرمتشده بهمراتب خواناتر خواهد بود و برای اشکالزدایی مناسبتر است.
ثبت دادههای ساختاریافته
لاگهای قدیمی معمولا متن ساده هستند. اما برای ثبت رویدادهای پیچیده، اقدامات کاربر یا وضعیتهای سیستم که بهصورت JSON بهتر نمایش داده میشوند، ثبت بهصورت یک رشته فشرده خوانایی و تحلیل را دشوار میکند.
این روش برای توسعه محلی مناسب میباشد، اما در محیطهای تولید، استفاده از سیستمهای مدیریت لاگ مانند ELK Splunk یا DataDog برای تجزیه دادهها به فیلدهای قابل جستجو کارآمدتر خواهد بود.
بهبود خوانایی فایلهای تنظیمات
فایلهای تنظیمات بخش مهمی از برنامهها هستند و مواردی مانند اتصالات پایگاه داده یا کلیدهای API را تعریف میکنند. فرمتبندی زیبا در موارد زیر کاربردی خواهد بود:
- زمانی که برنامهای فایل تنظیمات JSON را بهصورت فشرده تولید میکند، فرمتبندی زیبا آن را برای ویرایش دستی خوانا میکند.
- برای فایلهای تنظیمات دریافتشده از منابع خارجی، فرمتبندی زیبا ساختار و محتوا را آشکار میکند.
- هنگام اعمال تغییرات در فایلهای تنظیمات، فرمتبندی با تورفتگی ثابت و کلیدهای مرتبشده، تفاوتهای نسخه در سیستمهای کنترل نسخه مانند Git را واضحتر میکند.
سوالات متداول
در ادامه به سوالاتی که امکان دارد در این زمینه برای شما بدون پاسخ بماند، جوابهای کوتاه اما مفیدی دادهایم که با استفاده از آن میتوانید به سوال خود پاسخ صحیحی را بدهید.
بهترین روش برای تورفتگی خروجی JSON در پایتون چیست؟
سادهترین روش استفاده از پارامتر indent در تابع json.dumps() به صورت زیر خواهد بود.
import json
data = {"name": "Alice", "age": 30, "hobbies": ["reading", "chess", "hiking"]}
json_string = json.dumps(data, indent=4)
print(json_string)
تفاوت بین json.dumps() و pprint چیست؟
تابع json.dumps() اشیای پایتون را به رشتههای JSON معتبر تبدیل میکند و برای سریالسازی دادهها استفاده میشود. در مقابل، pprint ساختارهای داده پایتون را برای خوانایی در کنسول چاپ میکند و برای اشکالزدایی بهکار میرود.
ابزاری برای فرمتبندی خودکار JSON در اسکریپتهای پایتون وجود دارد؟
- ماژول
json.toolدر ترمینال:python -m json.tool input.json - ابزار
jq:jq . input.json(نیاز به نصب باpip install jq) - ویرایشگرهایی مانند VS Code و PyCharm با افزونههای فرمتبندی JSON.
جمع بندی
فرمتبندی JSON نهتنها دادهها را خواناتر میکند، بلکه ابزاری بسیار جذاب برای بهبود اشکالزدایی و مدیریت دادهها میباشد. با استفاده از تابع json.dumps() و ماژولهای مانند pprint، میتوانید خروجیهای واضح و ساختارمند تولید کنید. پارامترهای پیشرفته امکان مدیریت کاراکترهای غیرلاتین، سریالسازی اشیای سفارشی و بهینهسازی خروجی را فراهم میکنند.
این تکنیکها در اشکالزدایی پاسخهای API، ثبت دادههای ساختاریافته و بهبود خوانایی فایلهای تنظیمات کاربرد دارند. با ابزارهایی مانند ijson برای پردازش فایلهای بزرگ و کتابخانههای پرسرعت مانند orjson، میتوانید برنامههای خود را برای عملکرد و کارایی بهینه کنید. این رویکرد ساده اما مؤثر، تجربه توسعه را بهبود میبخشد و مدیریت دادهها را در هر سناریویی آسانتر میکند.