ToolDeck

تبدیل JSON به CSV در Python — مثال‌های DictWriter و pandas

·Backend Developer·بررسی‌شده توسطPriya Sharma·منتشر شده

از تبدیل 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 تخت است — هر مقدار در یک شبکه ردیف-ستون قرار می‌گیرد. تبدیل وقتی هر شیء همان مجموعه کلیدهای سطح اول را دارد به خوبی کار می‌کند. اشیاء تودرتو، آرایه‌ها، و کلیدهای ناسازگار جایی هستند که پیچیده می‌شود. داده‌های خام یکسان می‌مانند؛ فقط ساختار تغییر می‌کند.

After · json
Before · json
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 هم ترتیب ستون‌ها و هم کلیدهایی که در خروجی هستند را کنترل می‌کند.

Python 3.8+ — مثال ساده json به csv
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 استفاده کنید. همیشه گیج‌کننده است — یکی رشته می‌خواند، دیگری یک شیء فایل می‌خواند.

Python 3.8+ — خواندن فایل JSON و نوشتن فایل CSV
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 نیاز به قالب‌بندی صریح دارند تا از نمایش علمی جلوگیری شود.

Python 3.8+ — پیش‌پردازش datetime و Decimal قبل از نوشتن CSV
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 هستند.

پارامتر
نوع
مقدار پیش‌فرض
توضیح
f
file object
(الزامی)
هر شیئی با متد write() — معمولاً از open() به دست می‌آید
fieldnames
sequence
(الزامی)
لیست کلیدهایی که ترتیب ستون‌ها در خروجی CSV را مشخص می‌کند
restval
str
""
مقداری که وقتی یک dict کلیدی از fieldnames ندارد نوشته می‌شود
extrasaction
str
"raise"
"raise" برای کلیدهای اضافی ValueError می‌دهد؛ "ignore" آن‌ها را بی‌صدا حذف می‌کند
dialect
str / Dialect
"excel"
قوانین قالب‌بندی از پیش تعریف‌شده — "excel"، "excel-tab" یا "unix"
delimiter
str
","
یک کاراکتر جداکننده فیلدها — از "\t" برای خروجی TSV استفاده کنید
quotechar
str
"
کاراکتری که برای نقل‌قول فیلدهای حاوی جداکننده استفاده می‌شود
quoting
int
csv.QUOTE_MINIMAL
کنترل می‌کند چه زمانی نقل‌قول اعمال شود — MINIMAL، ALL، NONNUMERIC، NONE
lineterminator
str
"\r\n"
رشته‌ای که بعد از هر ردیف اضافه می‌شود — برای خروجی Unix-style به "\n" تغییر دهید

pandas — تبدیل JSON به CSV با DataFrameها

اگر قبلاً در یک codebase سنگین از pandas کار می‌کنید، یا JSON شما دارای اشیاء تودرتویی است که باید flatten شوند، رویکرد pandas به مراتب کد کمتری نسبت به نسخه stdlib دارد. البته pandas یک وابستگی ~۳۰ مگابایتی است. برای یک اسکریپت موقت، این مشکلی نیست. برای یک Docker image که به production می‌فرستید، رویکرد stdlib چیزها را سبک‌تر نگه می‌دارد.

Python 3.8+ — pandas read_json سپس to_csv
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 می‌کند.

Python 3.8+ — flatten کردن JSON تودرتو با json_normalize
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 اهمیت دارند.

پارامتر
نوع
مقدار پیش‌فرض
توضیح
path_or_buf
str / Path / None
None
مسیر فایل یا بافر — None مقدار CSV را به صورت رشته برمی‌گرداند
sep
str
","
جداکننده فیلد — از "\t" برای TSV استفاده کنید
index
bool
True
ایندکس ردیف را به عنوان اولین ستون می‌نویسد — تقریباً همیشه باید False باشد
columns
list
None
زیرمجموعه‌ای از ستون‌ها را انتخاب و مرتب‌سازی می‌کند
header
bool / list
True
نام ستون‌ها را می‌نویسد — وقتی به فایل موجود الحاق می‌کنید False بگذارید
encoding
str
"utf-8"
رمزنگاری خروجی — از "utf-8-sig" برای سازگاری با Excel در ویندوز استفاده کنید
na_rep
str
""
نمایش رشته‌ای برای مقادیر گمشده (NaN، None)
quoting
int
csv.QUOTE_MINIMAL
کنترل می‌کند چه زمانی فیلدها نقل‌قول گذاشته شوند
Python 3.8+ — to_csv با override پارامترهای رایج
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 لاگ می‌کنند، و یک شمارش ردیف برمی‌گردانند تا فراخوانندگان بتوانند خروجی‌های صفر ردیف را تشخیص داده و هشدار دهند.

فایل روی دیسک — خواندن، تبدیل، ذخیره

Python 3.8+ — تبدیل فایل JSON به CSV با مدیریت خطا
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 — دریافت و تبدیل

Python 3.8+ — دریافت JSON از API و ذخیره به عنوان CSV
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 برای شکل‌دهی مجدد داده استفاده کنید، سپس تبدیل کنید.

bash — تبدیل json به csv با one-liner
# 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
bash — اسکریپت CLI مستقل با argparse
# به عنوان 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)
" "$@"
bash — استفاده از jq + csvkit برای تبدیل‌های پیچیده
# نصب 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.csv

Miller (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 را تنظیم کنید.

bash — نصب pyarrow
pip install pyarrow
Python 3.8+ — pandas با pyarrow برای نوشتن سریع‌تر CSV
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 جداول با حاشیه، تراز، و رنگ در ترمینال رندر می‌کند — برای پیش‌نمایش یک تبدیل در طول توسعه بدون باز کردن فایل خروجی مفید است.

bash — نصب rich
pip install rich
Python 3.8+ — پیش‌نمایش خروجی CSV در ترمینال با 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)
# یک جدول رنگی با حاشیه در ترمینال رندر می‌کند
هشدار:Rich فقط برای نمایش ترمینال است. از آن برای تولید فایل‌های CSV استفاده نکنید — کدهای escape ANSI اضافه می‌کند که خروجی را خراب می‌کنند. با csv.DictWriter یا DataFrame.to_csv() به فایل‌ها بنویسید، و از rich فقط برای پیش‌نمایش استفاده کنید.

کار با فایل‌های JSON بزرگ

json.load() کل فایل را به حافظه می‌خواند. برای یک فایل JSON ۲۰۰ مگابایتی، این به معنای ~۲۰۰ مگابایت متن خام به علاوه سربار شیء Python است — به راحتی ۵۰۰ مگابایت+ استفاده از heap. برای فایل‌های بالای ۱۰۰ مگابایت، ورودی را با ijson پردازش جریانی کنید و ردیف‌های CSV را در حین پردازش بنویسید.

bash — نصب ijson
pip install ijson

پردازش جریانی آرایه JSON به CSV با ijson

Python 3.8+ — تبدیل جریانی آرایه JSON بزرگ به CSV با حافظه ثابت
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 است.

Python 3.8+ — تبدیل NDJSON به CSV خط به خط
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 از ۱۰۰ مگابایت بیشتر می‌شود به پردازش جریانی تغییر دهید. یک آرایه JSON یک گیگابایتی که با json.load() لود می‌شود می‌تواند به دلیل سربار شیء Python ۳-۵ گیگابایت RAM مصرف کند. با ijson، حافظه صرف‌نظر از اندازه فایل ثابت می‌ماند. اگر فقط به تبدیل سریع یک فایل کوچک نیاز دارید، آن را در مبدل JSON به CSV paste کنید.

اشتباهات رایج

فراموش کردن newline='' در open() — ردیف‌های خالی در ویندوز

مشکل: ماژول csv پایان‌بندی خط \r\n می‌نویسد. بدون newline=''، حالت text پایتون یک \r دیگر در ویندوز اضافه می‌کند که خروجی با فاصله مضاعف تولید می‌کند.

راه‌حل: همیشه newline='' را هنگام باز کردن فایل برای نوشتن CSV پاس بدهید. در macOS/Linux بی‌ضرر است.

After · Python
Before · Python
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 to_csv()

مشکل: بدون index=False، pandas یک ستون شماره ردیف با افزایش خودکار (0، 1، 2، ...) اضافه می‌کند که CSV را با داده‌ای که هرگز در JSON اصلی نبود آلوده می‌کند.

راه‌حل: index=False را به to_csv() پاس بدهید. اگر واقعاً به ستون index نیاز دارید، آن را به صراحت با df.index.name = 'row_num' نام‌گذاری کنید.

After · Python
Before · Python
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ها را خراب می‌کند
استفاده از records[0].keys() وقتی رکوردها کلیدهای ناسازگار دارند

مشکل: اگر اشیاء JSON کلیدهای مختلفی دارند (برخی رکوردها فیلدهای اختیاری دارند)، استفاده از کلیدهای اولین رکورد به عنوان fieldnames ستون‌هایی را که فقط در رکوردهای بعدی ظاهر می‌شوند بی‌صدا حذف می‌کند.

راه‌حل: قبل از ایجاد DictWriter تمام کلیدهای منحصربه‌فرد را در تمام رکوردها جمع‌آوری کنید.

After · Python
Before · Python
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] ظاهر می‌شود را از دست می‌دهد
نوشتن dicts تودرتو مستقیماً به CSV بدون flatten کردن

مشکل: csv.DictWriter روی dicts تودرتو str() فراخوانی می‌کند و ستون‌هایی با مقادیر مثل "{'city': 'Portland'}"تولید می‌کند — Python repr خام، نه داده واقعی.

راه‌حل: ابتدا اشیاء تودرتو را با pd.json_normalize() یا یک تابع flatten سفارشی flatten کنید.

After · Python
Before · Python
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_region
records = [{"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

روش
JSON تودرتو
انواع سفارشی
پردازش جریانی
وابستگی‌ها
نیاز به نصب
csv.DictWriter
✗ (flatten دستی)
✓ (ردیف به ردیف)
هیچ
خیر (stdlib)
csv.writer
✓ (ردیف به ردیف)
هیچ
خیر (stdlib)
pd.DataFrame.to_csv()
✗ (فقط flat)
✓ (از طریق dtypes)
pandas + numpy
pip install
pd.json_normalize() + to_csv()
✓ (از طریق dtypes)
pandas + numpy
pip install
csv.writer + json_flatten
flatten_json
pip install
jq + csvkit (CLI)
✓ (از طریق jq)
N/A
jq, csvkit
نصب سیستمی

از 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) جمع‌آوری کنید تا از افتادن ستون‌ها جلوگیری شود.

Python
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 و سازگاری با فرمول‌های صفحه‌گسترده بهتر است.

Python
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 به صراحت ذکر کرده است.

Python
# اشتباه — ردیف‌های خالی در ویندوز
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 آن بخوانید.

Python
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 هر خط را مستقل پردازش می‌کند.

Python
# سریع برای فایل‌هایی که در حافظه جا می‌شوند
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 مضاعف جلوگیری شود.

Python
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

ابزارهای مرتبط

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.

PS
Priya Sharmaبازبین فنی

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.