تبدیل JSON به CSV در Python — مثالهای DictWriter و pandas
از تبدیل JSON به CSV آنلاین رایگان مستقیم در مرورگرتان استفاده کنید — نیازی به نصب نیست.
امتحان کردن تبدیل JSON به CSV آنلاین ←تقریباً هر pipeline دادهای در نهایت به یک مرحله مشترک میرسد: یک API مقدار JSON برمیگرداند، اما مصرفکننده بعدی — یک صفحهگسترده، یک اسکریپت import، یک دستور Redshift COPY — به CSV نیاز دارد. تبدیل JSON به CSV در Python بیاهمیت به نظر میرسد تا وقتی با اشیاء تودرتو، کلیدهای ناسازگار، یا مقادیر datetime که نیاز به مدیریت خاص دارند روبرو شوید. Python دو مسیر قابل اطمینان ارائه میدهد: ماژولهای داخلی json + csv برای اسکریپتهای بدون وابستگی، و pandas برای flatten کردن دادههای تودرتو و مجموعه دادههای بزرگتر — یا مبدل آنلاین JSON به CSV برای تبدیلهای یکباره سریع بدون هیچ کدی. این راهنما هر دو رویکرد را از ابتدا تا انتها، با مثالهای قابل اجرا Python 3.8+ پوشش میدهد.
- ✓csv.DictWriter یک لیست از dicts را بدون هیچ وابستگی به CSV تبدیل میکند — از json.load() برای parse کردن استفاده کنید، سپس writeheader() + writerows().
- ✓همیشه فایلهای CSV را با newline="" در ویندوز باز کنید تا از ردیفهای خالی بین ردیفهای داده جلوگیری کنید.
- ✓pd.json_normalize() دادههای JSON تودرتو را قبل از فراخوانی to_csv() به یک DataFrame flat تبدیل میکند — سطوح مختلف تودرتو را به صورت خودکار مدیریت میکند.
- ✓index=False را به DataFrame.to_csv() پاس بدهید — بدون آن، pandas یک ستون شماره ردیف ناخواسته مینویسد.
- ✓برای فایلهای بالای ۵۰۰ مگابایت، از ijson برای parse کردن جریانی JSON همراه با csv.DictWriter برای استفاده ثابت از حافظه استفاده کنید.
تبدیل JSON به CSV چیست؟
تبدیل JSON به CSV یک آرایه از اشیاء JSON را به فرمت جدولی تبدیل میکند که در آن هر شیء یک ردیف و هر کلید یک سرستون میشود. JSON سلسلهمراتبی است — اشیاء میتوانند به صورت دلخواه تودرتو باشند. CSV تخت است — هر مقدار در یک شبکه ردیف-ستون قرار میگیرد. تبدیل وقتی هر شیء همان مجموعه کلیدهای سطح اول را دارد به خوبی کار میکند. اشیاء تودرتو، آرایهها، و کلیدهای ناسازگار جایی هستند که پیچیده میشود. دادههای خام یکسان میمانند؛ فقط ساختار تغییر میکند.
order_id,total,status ord_91a3,149.99,shipped ord_b7f2,34.50,pending
[{"order_id":"ord_91a3","total":149.99,"status":"shipped"},
{"order_id":"ord_b7f2","total":34.50,"status":"pending"}]csv.DictWriter — تبدیل JSON به CSV بدون Pandas
ماژول csv با هر نصب Python همراه است. بدون pip install، بدون دردسر virtual environment. csv.DictWriter یک لیست از dictionaryها میگیرد و هر کدام را به عنوان یک ردیف CSV مینویسد و کلیدهای dict را به سرستونها نگاشت میکند. پارامتر fieldnames هم ترتیب ستونها و هم کلیدهایی که در خروجی هستند را کنترل میکند.
import json
import csv
# دادههای JSON نمونه — آرایهای از اشیاء سفارش
json_string = """
[
{"order_id": "ord_91a3", "product": "Wireless Keyboard", "quantity": 2, "unit_price": 74.99},
{"order_id": "ord_b7f2", "product": "USB-C Hub", "quantity": 1, "unit_price": 34.50},
{"order_id": "ord_c4e8", "product": "Monitor Stand", "quantity": 3, "unit_price": 29.95}
]
"""
records = json.loads(json_string)
with open("orders.csv", "w", newline="", encoding="utf-8") as csvfile:
writer = csv.DictWriter(csvfile, fieldnames=records[0].keys())
writer.writeheader()
writer.writerows(records)
# orders.csv:
# order_id,product,quantity,unit_price
# ord_91a3,Wireless Keyboard,2,74.99
# ord_b7f2,USB-C Hub,1,34.50
# ord_c4e8,Monitor Stand,3,29.95آرگومان newline="" روی open() در ویندوز اختیاری نیست. بدون آن، double carriage return میگیرید — که در Excel به عنوان ردیفهای خالی بین هر ردیف داده نشان داده میشود. در macOS و Linux بیضرر است، پس همیشه آن را وارد کنید.
کد بالا از json.loads() برای یک رشته استفاده میکند. از json.load() (بدون s انتهایی) هنگام خواندن از یک file handle استفاده کنید. همیشه گیجکننده است — یکی رشته میخواند، دیگری یک شیء فایل میخواند.
import json
import csv
with open("server_metrics.json", encoding="utf-8") as jf:
metrics = json.load(jf) # json.load() برای اشیاء فایل
# fieldnames صریح ترتیب ستون را کنترل میکند
columns = ["timestamp", "hostname", "cpu_percent", "memory_mb", "disk_io_ops"]
with open("server_metrics.csv", "w", newline="", encoding="utf-8") as cf:
writer = csv.DictWriter(cf, fieldnames=columns, extrasaction="ignore")
writer.writeheader()
writer.writerows(metrics)
# فقط پنج ستون مشخصشده، دقیقاً با همان ترتیب، ظاهر میشوندتنظیم extrasaction="ignore" هر کلیدی در dicts که در لیست fieldnames شما نیست را بیصدا حذف میکند. مقدار پیشفرض "raise" است که اگر هر dict کلید غیرمنتظرهای داشته باشد یک ValueError میاندازد. هر کدام که با روش کارتان سازگارتر است را انتخاب کنید.
csv.DictWriter در مقابل csv.writer: DictWriter کلیدهای dict را به صورت خودکار به موقعیتهای ستون نگاشت میکند. csv.writer لیستهای خام را به عنوان ردیف مینویسد — شما خودتان ترتیب ستون را مدیریت میکنید. DictWriter تقریباً همیشه انتخاب درست برای JSON-به-CSV است چون رکوردهای JSON قبلاً dictionaryها هستند.ماژول csv پایتون با سه dialect نامگذاریشده همراه است: excel (جداکننده ویرگول، پایانبندی CRLF — پیشفرض), excel-tab (جداکننده tab، پایانبندی CRLF), و unix (پایانبندی LF، تمام فیلدهای غیرعددی را نقلقول میگذارد). نام dialect را به عنوان آرگومان dialect به csv.DictWriter پاس بدهید. همچنین میتوانید با csv.register_dialect() یک dialect سفارشی تعریف کنید وقتی سیستم هدف شما قوانین نقلقول یا جداکننده غیرمعمولی دارد. برای اکثر workflowهای JSON-به-CSV dialect excel درست است، اما وقتی فایلهایی مینویسید که توسط ابزارهای POSIX مانند awk یا sort پردازش میشوند به unix تغییر دهید.
مدیریت انواع غیراستاندارد: datetime، UUID، و Decimal
JSON از APIها اغلب شامل تاریخها به عنوان رشتههای ISO، UUIDها به عنوان رشتههای خطدار، و مقادیر پولی به عنوان float است. وقتی اینها را قبل از نوشتن CSV به اشیاء Python تبدیل میکنید، باید آنها را به رشته برگردانید. ماژول csv روی هر مقدار str() فراخوانی میکند، بنابراین اکثر انواع به درستی کار میکنند. اما اشیاء datetime نمایش رشتهای پیشفرض نامرتبی دارند، و مقادیر Decimal نیاز به قالببندی صریح دارند تا از نمایش علمی جلوگیری شود.
import json
import csv
from datetime import datetime, timezone
from decimal import Decimal
from uuid import UUID
# شبیهسازی پاسخ API پارسشده با انواع Python
transactions = [
{
"txn_id": UUID("a1b2c3d4-e5f6-7890-abcd-ef1234567890"),
"created_at": datetime(2026, 3, 15, 9, 30, 0, tzinfo=timezone.utc),
"amount": Decimal("1249.99"),
"currency": "USD",
"merchant": "CloudHost Inc.",
},
{
"txn_id": UUID("b2c3d4e5-f6a7-8901-bcde-f12345678901"),
"created_at": datetime(2026, 3, 15, 14, 12, 0, tzinfo=timezone.utc),
"amount": Decimal("87.50"),
"currency": "EUR",
"merchant": "DataSync GmbH",
},
]
def prepare_row(record: dict) -> dict:
"""انواع غیررشتهای را به رشتههای مناسب CSV تبدیل میکند."""
return {
"txn_id": str(record["txn_id"]),
"created_at": record["created_at"].isoformat(),
"amount": f"{record['amount']:.2f}",
"currency": record["currency"],
"merchant": record["merchant"],
}
with open("transactions.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=["txn_id", "created_at", "amount", "currency", "merchant"])
writer.writeheader()
for txn in transactions:
writer.writerow(prepare_row(txn))
# transactions.csv:
# txn_id,created_at,amount,currency,merchant
# a1b2c3d4-e5f6-7890-abcd-ef1234567890,2026-03-15T09:30:00+00:00,1249.99,USD,CloudHost Inc.
# b2c3d4e5-f6a7-8901-bcde-f12345678901,2026-03-15T14:12:00+00:00,87.50,EUR,DataSync GmbHتابع prepare_row() رویکرد درست اینجاست. به جای تلاش برای آموزش دادن به csv.DictWriter درباره انواع سفارشی، هر رکورد را قبل از نوشتن به رشتهها نرمال میکنید. ترجیح میدهم.isoformat() را به صراحت روی اشیاء datetime فراخوانی کنم تا به str() متکی باشم — فرمت خروجی قابل پیشبینیتر است و پارسرهای downstream به طور قابل اعتماد ISO 8601 را مدیریت میکنند.
Decimal را بدون قالببندی رد کنید، اعداد بسیار کوچک یا بسیار بزرگ ممکن است در نمایش علمی رندر شوند (مثلاً 1.5E+7). همیشه Decimal را با یک f-string صریح مثل f"{value:.2f}" هنگام نوشتن دادههای مالی به CSV قالببندی کنید.یک الگوی جایگزین برای pipelineهایی با انواع سفارشی زیاد، گسترش json.JSONEncoder است. آن را subclass کنید، متد default() را override کنید تا برای هر نوع سفارشی یک مقدار JSON-serializable برگرداند، سپس subclass را به عنوان آرگومان cls به json.dumps() پاس بدهید. رمزگذاری مجدد از طریق encoder سفارشی قبل از نوشتن به CSV همه انواع را در یک مرحله نرمال میکند بدون فراخوانی prepare_row() به ازای هر ردیف. الگوی prepare_row() نشان دادهشده در بالا برای اسکریپتهای یکباره سادهتر است؛ رویکرد subclass JSONEncoder وقتی یک domain model با انواع سفارشی در چند pipeline یا میکروسرویس استفاده میشود بهتر scale میکند.
مرجع پارامترهای csv.DictWriter
امضای کامل سازنده csv.DictWriter(f, fieldnames, restval="", extrasaction="raise", dialect="excel", **fmtparams) است. بیشتر اینها مقادیر پیشفرض معقولی دارند. آنهایی که واقعاً تغییر میدهید fieldnames، delimiter، و extrasaction هستند.
pandas — تبدیل JSON به CSV با DataFrameها
اگر قبلاً در یک codebase سنگین از pandas کار میکنید، یا JSON شما دارای اشیاء تودرتویی است که باید flatten شوند، رویکرد pandas به مراتب کد کمتری نسبت به نسخه stdlib دارد. البته pandas یک وابستگی ~۳۰ مگابایتی است. برای یک اسکریپت موقت، این مشکلی نیست. برای یک Docker image که به production میفرستید، رویکرد stdlib چیزها را سبکتر نگه میدارد.
import pandas as pd
# آرایه JSON را مستقیماً به DataFrame بخوانید
df = pd.read_json("warehouse_inventory.json")
# به CSV بنویسید — index=False از اضافه شدن شماره ردیف خودکار جلوگیری میکند
df.to_csv("warehouse_inventory.csv", index=False)
# همین. دو خط. pandas انواع ستون را به صورت خودکار استنتاج میکند.پرچم index=False یکی از آن چیزهایی است که هر بار باید جستجو کنید. بدون آن، pandas یک ستون 0, 1, 2, ... به عنوان اولین ستون CSV مینویسد. هیچکس این را نمیخواهد.
Flatten کردن JSON تودرتو با json_normalize
پاسخهای واقعی API به ندرت تخت هستند. سفارشات حاوی آدرسهای ارسال، کاربران حاوی تنظیمات تودرتو، رویدادهای تلهمتری حاوی متادیتای تودرتو هستند. pd.json_normalize() dictionaryهای تودرتو را پیمایش کرده و آنها را به ستونهایی با نامهای جدا شده با نقطه flatten میکند.
import json
import pandas as pd
api_response = """
[
{
"order_id": "ord_91a3",
"placed_at": "2026-03-15T09:30:00Z",
"customer": {
"name": "Sarah Chen",
"email": "s.chen@example.com",
"tier": "premium"
},
"shipping": {
"method": "express",
"address": {
"city": "Portland",
"state": "OR",
"zip": "97201"
}
},
"total": 299.95
},
{
"order_id": "ord_b7f2",
"placed_at": "2026-03-15T14:12:00Z",
"customer": {
"name": "James Park",
"email": "j.park@example.com",
"tier": "standard"
},
"shipping": {
"method": "standard",
"address": {
"city": "Austin",
"state": "TX",
"zip": "73301"
}
},
"total": 87.50
}
]
"""
orders = json.loads(api_response)
# json_normalize dicts تودرتو را flatten میکند — sep جداکننده را کنترل میکند
df = pd.json_normalize(orders, sep="_")
df.to_csv("flat_orders.csv", index=False)
# ستونهای نتیجه:
# order_id, placed_at, customer_name, customer_email, customer_tier,
# shipping_method, shipping_address_city, shipping_address_state,
# shipping_address_zip, totalپارامتر sep="_" کنترل میکند نامهای کلید تودرتو چطور به هم وصل شوند. پیشفرض "." است که ستونهایی مثل customer.name تولید میکند. زیرخط را ترجیح میدهم چون نقطه در نام ستونها با واردسازی SQL و برخی فرمولهای صفحهگسترده مشکل ایجاد میکند.
برای پاسخهای API که آرایه رکوردها را زیر یک کلید تودرتو قرار میدهند، از پارامتر record_path استفاده کنید. اگر پاسخ شبیه {"data": {"orders": [...]}} است،record_path=["data", "orders"] را پاس بدهید تا به لیست درست برسید. پارامتر اختیاری meta به شما اجازه میدهد فیلدهای سطح والد را کنار رکوردهای تودرتو بکشید — مفید وقتی پاسخ شامل اطلاعات pagination سطح بالا (شماره صفحه، تعداد کل) است که میخواهید در هر ردیف به عنوان ستون باشد. record_path و meta با هم اکثر شکلهای پاسخ API تودرتو دنیای واقعی را بدون پیشپردازش سفارشی مدیریت میکنند.
مرجع پارامترهای DataFrame.to_csv()
DataFrame.to_csv() بیش از ۲۰ پارامتر دارد. اینها آنهایی هستند که برای workflowهای JSON-به-CSV اهمیت دارند.
import pandas as pd
df = pd.read_json("telemetry_events.json")
# خروجی TSV با رمزنگاری صریح و مدیریت مقدار گمشده
df.to_csv(
"telemetry_events.tsv",
sep="\t",
index=False,
encoding="utf-8",
na_rep="NULL",
columns=["event_id", "timestamp", "source", "severity", "message"],
)
# نوشتن به stdout برای pipe کردن در shell script
print(df.to_csv(index=False))
# برگرداندن به صورت رشته (بدون نوشتن فایل)
csv_string = df.to_csv(index=False)
print(len(csv_string), "characters")تبدیل JSON به CSV از فایل و پاسخ API
دو سناریوی رایج دنیای واقعی: خواندن JSON از یک فایل روی دیسک و تبدیل آن، یا گرفتن JSON از یک HTTP API و ذخیره نتیجه به عنوان CSV. در توسعه میتوانید بدون مدیریت خطا کار کنید. در production، این انتخاب تبدیل به یک هشدار ساعت ۲ شب میشود. فایلها ممکن است وجود نداشته باشند، APIها ممکن است کد وضعیت ۴xx یا ۵xx به جای JSON برگردانند، بدنه پاسخ ممکن است یک شیء خطا به جای آرایه باشد، یا JSON ممکن است به دلیل timeout شبکه ناقص باشد. الگوهای زیر تمام این موارد را به صراحت مدیریت میکنند، خطاها را به stderr لاگ میکنند، و یک شمارش ردیف برمیگردانند تا فراخوانندگان بتوانند خروجیهای صفر ردیف را تشخیص داده و هشدار دهند.
فایل روی دیسک — خواندن، تبدیل، ذخیره
import json
import csv
import sys
def json_file_to_csv(input_path: str, output_path: str) -> int:
"""یک فایل JSON حاوی آرایهای از اشیاء را به CSV تبدیل میکند.
تعداد ردیفهای نوشتهشده را برمیگرداند.
"""
try:
with open(input_path, encoding="utf-8") as jf:
data = json.load(jf)
except FileNotFoundError:
print(f"Error: {input_path} not found", file=sys.stderr)
return 0
except json.JSONDecodeError as exc:
print(f"Error: invalid JSON in {input_path}: {exc.msg} at line {exc.lineno}", file=sys.stderr)
return 0
if not isinstance(data, list) or not data:
print(f"Error: expected a non-empty JSON array in {input_path}", file=sys.stderr)
return 0
# جمعآوری همه کلیدهای منحصربهفرد در تمام رکوردها — schemaهای ناسازگار را مدیریت میکند
all_keys: list[str] = []
seen: set[str] = set()
for record in data:
for key in record:
if key not in seen:
all_keys.append(key)
seen.add(key)
with open(output_path, "w", newline="", encoding="utf-8") as cf:
writer = csv.DictWriter(cf, fieldnames=all_keys, restval="", extrasaction="ignore")
writer.writeheader()
writer.writerows(data)
return len(data)
rows = json_file_to_csv("deploy_logs.json", "deploy_logs.csv")
print(f"Wrote {rows} rows to deploy_logs.csv")پاسخ HTTP API — دریافت و تبدیل
import json
import csv
import urllib.request
import urllib.error
def api_response_to_csv(url: str, output_path: str) -> int:
"""JSON را از یک endpoint REST API دریافت کرده و به عنوان CSV مینویسد."""
try:
req = urllib.request.Request(url, headers={"Accept": "application/json"})
with urllib.request.urlopen(req, timeout=30) as resp:
if resp.status != 200:
print(f"Error: API returned status {resp.status}")
return 0
body = resp.read().decode("utf-8")
except urllib.error.URLError as exc:
print(f"Error: could not reach {url}: {exc.reason}")
return 0
try:
records = json.loads(body)
except json.JSONDecodeError as exc:
print(f"Error: API returned invalid JSON: {exc.msg}")
return 0
if not isinstance(records, list) or not records:
print("Error: expected a non-empty JSON array from the API")
return 0
with open(output_path, "w", newline="", encoding="utf-8") as cf:
writer = csv.DictWriter(cf, fieldnames=records[0].keys())
writer.writeheader()
writer.writerows(records)
return len(records)
rows = api_response_to_csv(
"https://api.internal.example.com/v2/deployments?status=completed",
"completed_deployments.csv",
)
print(f"Exported {rows} deployments to CSV")urllib از کتابخانه استاندارد استفاده میکند تا اسکریپت بدون وابستگی بماند. اگر requests نصب شده دارید، بخش urllib را با resp = requests.get(url, timeout=30); records = resp.json() جایگزین کنید — بقیه کد نوشتن CSV یکسان میماند.تبدیل JSON به CSV از طریق خط فرمان
گاهی فقط به یک one-liner در ترمینال نیاز دارید. پرچم -c پایتون به شما اجازه میدهد بدون ایجاد فایل اسکریپت یک تبدیل سریع انجام دهید. برای تبدیلهای پیچیدهتر، ابتدا از jq برای شکلدهی مجدد داده استفاده کنید، سپس تبدیل کنید.
# Python one-liner: JSON را از stdin میخواند، CSV را به stdout مینویسد cat orders.json | python3 -c " import json, csv, sys data = json.load(sys.stdin) w = csv.DictWriter(sys.stdout, fieldnames=data[0].keys()) w.writeheader() w.writerows(data) " # ذخیره خروجی در فایل cat orders.json | python3 -c " import json, csv, sys data = json.load(sys.stdin) w = csv.DictWriter(sys.stdout, fieldnames=data[0].keys()) w.writeheader() w.writerows(data) " > orders.csv
# به عنوان json2csv.py ذخیره کنید و اجرا کنید: python3 json2csv.py input.json -o output.csv
python3 -c "
import json, csv, argparse, sys
parser = argparse.ArgumentParser(description='Convert JSON array to CSV')
parser.add_argument('input', help='Path to JSON file')
parser.add_argument('-o', '--output', default=None, help='Output CSV path (default: stdout)')
parser.add_argument('-d', '--delimiter', default=',', help='CSV delimiter')
args = parser.parse_args()
with open(args.input) as f:
data = json.load(f)
out = open(args.output, 'w', newline='') if args.output else sys.stdout
writer = csv.DictWriter(out, fieldnames=data[0].keys(), delimiter=args.delimiter)
writer.writeheader()
writer.writerows(data)
if args.output:
out.close()
print(f'Wrote {len(data)} rows to {args.output}', file=sys.stderr)
" "$@"# نصب csvkit: pip install csvkit
# jq فیلدها را انتخاب و flatten میکند، in2csv قالببندی CSV را انجام میدهد
cat api_response.json | jq '[.[] | {id: .order_id, customer: .customer.name, total}]' | in2csv -f json > orders.csv
# Miller (mlr) گزینه دیگری برای JSON-به-CSV است
mlr --json2csv cat orders.json > orders.csvMiller (mlr) یک فایل باینری مستقل است که JSON، CSV، و TSV را به عنوان فرمتهای درجه اول بدون نیاز به Python runtime مدیریت میکند. پرچم --json2csv ورودی JSON را در یک پاس به CSV تبدیل میکند، و میتوانید verbهای Miller را برای فیلتر، مرتبسازی، یا تغییر نام ستونها در همان دستور قبل از نوشتن خروجی زنجیر کنید. از طریق Homebrew در macOS نصب کنید (brew install miller) یا مدیر بسته Linux خود. به ویژه در CI pipelineها مفید است جایی که میخواهید تبدیل سریع JSON-به-CSV بدون راهاندازی محیط Python داشته باشید.
گزینه High-Performance — pandas با pyarrow
برای مجموعه دادههایی در محدوده دهها میلیون ردیف، pandas با backend pyarrow به طور قابل توجهی سریعتر از پیشفرض میخواند و مینویسد. موتور Arrow با پشتیبانی C دادههای ستونی را کارآمدتر از ماژول csv ردیف به ردیف پایتون پردازش میکند. API یکسان میماند — فقط پارامتر engine را تنظیم کنید.
pip install pyarrow
import pandas as pd
# خواندن JSON با موتور pyarrow (parse کردن سریعتر برای فایلهای بزرگ)
df = pd.read_json("sensor_readings.json", engine="pyarrow")
# to_csv پارامتر engine ندارد، اما عملیات DataFrame
# بین خواندن و نوشتن از layout ستونی pyarrow بهره میبرند
df.to_csv("sensor_readings.csv", index=False)
# برای exportهای واقعاً بزرگ، به جای CSV به Parquet بنویسید
# — فرمت باینری، ۵-۱۰ برابر کوچکتر، انواع را حفظ میکند
df.to_parquet("sensor_readings.parquet", engine="pyarrow")اگر بیش از چند صد مگابایت JSON پردازش میکنید و مصرفکننده نهایی Parquet را قبول میکند، CSV را کلاً نادیده بگیرید. Parquet کوچکتر است، انواع ستون را حفظ میکند، و هم Redshift و هم BigQuery آن را به صورت بومی لود میکنند. CSV یک فرمت lossy است — هر مقداری تبدیل به رشته میشود.
خروجی ترمینال با Syntax Highlighting
کتابخانه rich جداول با حاشیه، تراز، و رنگ در ترمینال رندر میکند — برای پیشنمایش یک تبدیل در طول توسعه بدون باز کردن فایل خروجی مفید است.
pip install rich
import json
from rich.console import Console
from rich.table import Table
json_string = """
[
{"hostname": "web-prod-1", "cpu_percent": 72.3, "memory_mb": 3840, "uptime_hours": 720},
{"hostname": "web-prod-2", "cpu_percent": 45.1, "memory_mb": 2560, "uptime_hours": 168},
{"hostname": "db-replica-1", "cpu_percent": 91.7, "memory_mb": 7680, "uptime_hours": 2160}
]
"""
records = json.loads(json_string)
console = Console()
table = Table(title="Server Metrics Preview", show_lines=True)
for key in records[0]:
table.add_column(key, style="cyan" if key == "hostname" else "white")
for row in records:
table.add_row(*[str(v) for v in row.values()])
console.print(table)
# یک جدول رنگی با حاشیه در ترمینال رندر میکندcsv.DictWriter یا DataFrame.to_csv() به فایلها بنویسید، و از rich فقط برای پیشنمایش استفاده کنید.کار با فایلهای JSON بزرگ
json.load() کل فایل را به حافظه میخواند. برای یک فایل JSON ۲۰۰ مگابایتی، این به معنای ~۲۰۰ مگابایت متن خام به علاوه سربار شیء Python است — به راحتی ۵۰۰ مگابایت+ استفاده از heap. برای فایلهای بالای ۱۰۰ مگابایت، ورودی را با ijson پردازش جریانی کنید و ردیفهای CSV را در حین پردازش بنویسید.
pip install ijson
پردازش جریانی آرایه JSON به CSV با ijson
import ijson
import csv
def stream_json_to_csv(json_path: str, csv_path: str) -> int:
"""یک آرایه JSON بزرگ را بدون لود کردن کامل آن به حافظه به CSV تبدیل میکند."""
with open(json_path, "rb") as jf, open(csv_path, "w", newline="", encoding="utf-8") as cf:
# ijson.items هر عنصر آرایه سطح اول را یکییکی yield میکند
records = ijson.items(jf, "item")
first_record = next(records)
fieldnames = list(first_record.keys())
writer = csv.DictWriter(cf, fieldnames=fieldnames)
writer.writeheader()
writer.writerow(first_record)
count = 1
for record in records:
writer.writerow(record)
count += 1
return count
rows = stream_json_to_csv("clickstream_2026_03.json", "clickstream_2026_03.csv")
print(f"Streamed {rows} records to CSV")NDJSON / JSON Lines — یک شیء در هر خط
NDJSON (Newline-Delimited JSON)، که JSON Lines یا .jsonl هم نامیده میشود، یک شیء JSON معتبر در هر خط بدون آرایه پوششدهنده ذخیره میکند. این فرمت در pipelineهای لاگ، جریانهای رویداد (Kafka، Kinesis)، و exportهای bulk از سرویسهایی مثل Elasticsearch و BigQuery رایج است. چون هر خط یک شیء JSON مستقل است، میتوانید یک فایل NDJSON را با یک حلقه for ساده پایتون روی file handle پردازش کنید — نیازی به کتابخانه ijson نیست. حافظه بدون توجه به اندازه فایل ثابت میماند و این را سادهترین رویکرد پردازش جریانی میکند وقتی داده منبع قبلاً در فرمت JSON Lines است.
import json
import csv
def ndjson_to_csv(ndjson_path: str, csv_path: str) -> int:
"""یک فایل JSON newline-delimited را به CSV تبدیل میکند، یک خط در یک زمان."""
with open(ndjson_path, encoding="utf-8") as nf:
first_line = nf.readline()
first_record = json.loads(first_line)
fieldnames = list(first_record.keys())
with open(csv_path, "w", newline="", encoding="utf-8") as cf:
writer = csv.DictWriter(cf, fieldnames=fieldnames)
writer.writeheader()
writer.writerow(first_record)
count = 1
for line in nf:
line = line.strip()
if not line:
continue
try:
record = json.loads(line)
writer.writerow(record)
count += 1
except json.JSONDecodeError:
continue # خطوط ناقص را نادیده بگیرید
return count
rows = ndjson_to_csv("access_log.ndjson", "access_log.csv")
print(f"Converted {rows} log entries to CSV")json.load() لود میشود میتواند به دلیل سربار شیء Python ۳-۵ گیگابایت RAM مصرف کند. با ijson، حافظه صرفنظر از اندازه فایل ثابت میماند. اگر فقط به تبدیل سریع یک فایل کوچک نیاز دارید، آن را در مبدل JSON به CSV paste کنید.اشتباهات رایج
مشکل: ماژول csv پایانبندی خط \r\n مینویسد. بدون newline=''، حالت text پایتون یک \r دیگر در ویندوز اضافه میکند که خروجی با فاصله مضاعف تولید میکند.
راهحل: همیشه newline='' را هنگام باز کردن فایل برای نوشتن CSV پاس بدهید. در macOS/Linux بیضرر است.
with open("output.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=columns)
writer.writeheader()
writer.writerows(data)
# خروجی تمیز در همه پلتفرمهاwith open("output.csv", "w") as f:
writer = csv.DictWriter(f, fieldnames=columns)
writer.writeheader()
writer.writerows(data)
# ردیفهای خالی بین هر ردیف داده در ویندوزمشکل: بدون index=False، pandas یک ستون شماره ردیف با افزایش خودکار (0، 1، 2، ...) اضافه میکند که CSV را با دادهای که هرگز در JSON اصلی نبود آلوده میکند.
راهحل: index=False را به to_csv() پاس بدهید. اگر واقعاً به ستون index نیاز دارید، آن را به صراحت با df.index.name = 'row_num' نامگذاری کنید.
df = pd.read_json("events.json")
df.to_csv("events.csv", index=False)
# CSV تمیز: event_id,timestamp,...df = pd.read_json("events.json")
df.to_csv("events.csv")
# CSV یک ستون بدون نام اضافه میگیرد: ,event_id,timestamp,...
# ویرگول ابتدایی بسیاری از CSV parserها را خراب میکندمشکل: اگر اشیاء JSON کلیدهای مختلفی دارند (برخی رکوردها فیلدهای اختیاری دارند)، استفاده از کلیدهای اولین رکورد به عنوان fieldnames ستونهایی را که فقط در رکوردهای بعدی ظاهر میشوند بیصدا حذف میکند.
راهحل: قبل از ایجاد DictWriter تمام کلیدهای منحصربهفرد را در تمام رکوردها جمعآوری کنید.
records = json.load(f) all_keys = list(dict.fromkeys(k for r in records for k in r)) writer = csv.DictWriter(out, fieldnames=all_keys, restval="") # هر کلید از هر رکورد به عنوان ستون اضافه میشود
records = json.load(f) writer = csv.DictWriter(out, fieldnames=records[0].keys()) # فیلد "discount" که فقط در records[2] ظاهر میشود را از دست میدهد
مشکل: csv.DictWriter روی dicts تودرتو str() فراخوانی میکند و ستونهایی با مقادیر مثل "{'city': 'Portland'}"تولید میکند — Python repr خام، نه داده واقعی.
راهحل: ابتدا اشیاء تودرتو را با pd.json_normalize() یا یک تابع flatten سفارشی flatten کنید.
import pandas as pd
records = [{"id": "evt_1", "meta": {"source": "web", "region": "us-west"}}]
df = pd.json_normalize(records, sep="_")
df.to_csv("events.csv", index=False)
# ستونها: id, meta_source, meta_regionrecords = [{"id": "evt_1", "meta": {"source": "web", "region": "us-west"}}]
writer = csv.DictWriter(f, fieldnames=["id", "meta"])
writer.writerows(records)
# ستون meta شامل: {'source': 'web', 'region': 'us-west'}مقایسه سریع csv.DictWriter در برابر pandas
از csv.DictWriter استفاده کنید وقتی به صفر وابستگی نیاز دارید، JSON شما تخت است، و اسکریپت در یک محیط محدود اجرا میشود (CI containerها، Lambda functionها، Python تعبیهشده). از pd.json_normalize() + to_csv() استفاده کنید وقتی JSON تودرتو است، باید قبل از export داده را تبدیل یا فیلتر کنید، یا قبلاً در یک workflow pandas هستید. برای فایلهایی که در حافظه جا نمیشوند، ijson را با csv.DictWriter برای پردازش جریانی با حافظه ثابت ترکیب کنید.
برای تبدیلهای سریع بدون کد، مبدل JSON به CSV در ToolDeck بدون هیچ تنظیمات Python آن را انجام میدهد.
سوالات متداول
چطور بدون pandas در Python فایل JSON را به CSV تبدیل کنم؟
از ماژولهای داخلی json و csv استفاده کنید. با json.load() فایل JSON را به لیستی از dicts تبدیل کنید، fieldnames را از کلیدهای اولین dict استخراج کنید، یک csv.DictWriter بسازید، writeheader() و سپس writerows() را فراخوانی کنید. این رویکرد هیچ وابستگی خارجی ندارد و در هر محیط Python 3.x کار میکند. همچنین برای فایلهای کوچک سریعتر از pandas است چون سربار تخصیص DataFrame وجود ندارد. اگر اشیاء JSON در رکوردها کلیدهای ناسازگار دارند، ابتدا تمام کلیدهای منحصربهفرد را با dict.fromkeys(k for r in records for k in r) جمعآوری کنید تا از افتادن ستونها جلوگیری شود.
import json
import csv
with open("orders.json") as f:
records = json.load(f)
with open("orders.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=records[0].keys())
writer.writeheader()
writer.writerows(records)هنگام تبدیل JSON تودرتو به CSV چطور عمل کنم؟
آرایههای JSON تخت مستقیماً به ردیفهای CSV تبدیل میشوند، اما اشیاء تودرتو باید ابتدا flatten شوند. با pandas، pd.json_normalize() این کار را به صورت خودکار انجام میدهد — کلیدهای تودرتو را با جداکننده نقطه به هم وصل میکند (مثلاً "address.city"). بدون pandas، یک تابع بازگشتی بنویسید که dict را پیمایش کرده و کلیدها را با یک جداکننده به هم وصل کند. برای ساختارهای عمیقاً تودرتو با چندین سطح، json_normalize همه را در یک پاس مدیریت میکند. پارامتر sep کاراکتر اتصال بین بخشهای کلید را کنترل میکند — زیرخط معمولاً از نقطه پیشفرض برای واردسازی SQL و سازگاری با فرمولهای صفحهگسترده بهتر است.
import pandas as pd
nested_data = [
{"id": "ord_91a3", "customer": {"name": "فاطمه احمدی", "email": "f.ahmadi@example.com"}},
]
df = pd.json_normalize(nested_data, sep="_")
# ستونها: id, customer_name, customer_email
df.to_csv("flat_orders.csv", index=False)چرا در ویندوز بین ردیفهای داده در CSV خطوط خالی وجود دارد؟
ماژول csv به طور پیشفرض پایانبندی خط \r\n مینویسد. در ویندوز، باز کردن فایل در حالت text mode یک \r دیگر اضافه میکند که \r\r\n تولید میکند — که به عنوان ردیف خالی نمایش داده میشود. راهحل این است که همیشه newline="" را به open() پاس بدهید. این به Python میگوید پایانبندی خطوط را ترجمه نکند و به ماژول csv اجازه دهد آنها را مدیریت کند. این الگو صرفنظر از سیستمعامل الزامی است — در macOS و Linux بیضرر است و در ویندوز حیاتی است. مستندات Python این موضوع را در بخش ماژول csv به عنوان روش صحیح باز کردن فایل برای نوشتن CSV به صراحت ذکر کرده است.
# اشتباه — ردیفهای خالی در ویندوز
with open("output.csv", "w") as f:
writer = csv.writer(f)
# درست — newline="" از \r مضاعف جلوگیری میکند
with open("output.csv", "w", newline="") as f:
writer = csv.writer(f)چطور رکوردهای JSON را به یک فایل CSV موجود الحاق کنم؟
فایل را در حالت append ("a") باز کنید و یک DictWriter با همان fieldnames بسازید. writeheader() را فراخوانی نکنید چون ردیف header قبلاً وجود دارد. با pandas از to_csv(mode="a", header=False) استفاده کنید. مطمئن شوید ترتیب ستونها با فایل موجود مطابقت دارد وگرنه دادهها در ستونهای اشتباه قرار میگیرند. اگر از ترتیب ستونها در فایل موجود مطمئن نیستید، ابتدا آن را با csv.DictReader باز کنید و fieldnames را از ویژگی fieldnames آن بخوانید.
import csv
new_records = [
{"order_id": "ord_f4c1", "total": 89.50, "status": "shipped"},
]
with open("orders.csv", "a", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=["order_id", "total", "status"])
writer.writerows(new_records)سریعترین روش برای تبدیل یک فایل JSON بزرگ به CSV در Python چیست؟
برای فایلهای زیر ۵۰۰ مگابایت، pd.read_json() و سپس to_csv() سریعترین رویکرد تکفراخوانی است — pandas از کد C بهینهشده استفاده میکند. برای فایلهای بالای ۵۰۰ مگابایت، از ijson برای پردازش جریانی رکوردهای JSON استفاده کنید و آنها را با csv.DictWriter ردیف به ردیف بنویسید. این روش استفاده از حافظه را صرفنظر از اندازه فایل ثابت نگه میدارد. برای فایلهای NDJSON (یک شیء JSON در هر خط)، اصلاً به ijson نیاز ندارید — یک حلقه for ساده روی file handle هر خط را مستقل پردازش میکند.
# سریع برای فایلهایی که در حافظه جا میشوند
import pandas as pd
df = pd.read_json("large_dataset.json")
df.to_csv("large_dataset.csv", index=False)
# پردازش جریانی برای فایلهایی که در حافظه جا نمیشوند
import ijson, csv
with open("huge.json", "rb") as jf, open("huge.csv", "w", newline="") as cf:
records = ijson.items(jf, "item")
first = next(records)
writer = csv.DictWriter(cf, fieldnames=first.keys())
writer.writeheader()
writer.writerow(first)
for record in records:
writer.writerow(record)آیا میتوانم خروجی CSV را به جای فایل به stdout بنویسم؟
بله. sys.stdout را به عنوان آرگومان file به csv.writer() یا csv.DictWriter() پاس بدهید. این برای pipe کردن خروجی در shell script یا دیباگ سریع مفید است. با pandas، to_csv(sys.stdout, index=False) یا to_csv(None) را فراخوانی کنید تا یک رشته بگیرید که میتوانید print کنید. نیازی به فایل موقت نیست. هنگام نوشتن به stdout در ویندوز، ابتدا sys.stdout.reconfigure(newline="") را فراخوانی کنید تا از مشکل carriage-return مضاعف جلوگیری شود.
import csv
import sys
import json
data = json.loads('[{"host":"web-1","cpu":72.3},{"host":"web-2","cpu":45.1}]')
writer = csv.DictWriter(sys.stdout, fieldnames=data[0].keys())
writer.writeheader()
writer.writerows(data)
# host,cpu
# web-1,72.3
# web-2,45.1ابزارهای مرتبط
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.
Priya is a data scientist and machine learning engineer who has worked across the full Python data stack — from raw data ingestion and cleaning to model deployment and monitoring. She is passionate about reproducible research, Jupyter-based workflows, and the practical engineering side of ML. She writes about NumPy, Pandas, data serialisation, and the Python patterns that make data pipelines reliable at scale.