JSON do CSV v Pythonu — Příklady DictWriter a pandas

·Backend Developer·ZkontrolovánoPriya Sharma·Publikováno

Používejte bezplatný JSON to CSV přímo v prohlížeči — bez instalace.

Vyzkoušet JSON to CSV online →

Téměř každý datový pipeline narazí nakonec na stejný krok: API vrátí JSON, ale další konzument — tabulkový procesor, importní skript, příkaz Redshift COPY — potřebuje CSV. Převod JSON na CSV v Pythonu zní triviálně, dokud nenarazíte na vnořené objekty, nekonzistentní klíče nebo hodnoty datetime vyžadující speciální zpracování. Python nabízí dvě solidní cesty: vestavěné moduly json + csv pro skripty bez závislostí, a pandas pro zploštění vnořených struktur a větší datové sady — nebo online převodník JSON na CSV pro rychlé jednorázové konverze bez jakéhokoli kódu. Tento průvodce pokrývá oba přístupy od začátku do konce s funkčními příklady pro Python 3.8+.

  • csv.DictWriter převede seznam slovníků na CSV bez závislostí — použijte json.load() pro parsování a poté writeheader() + writerows().
  • Vždy otevírejte CSV soubory s newline="" na Windows, abyste předešli prázdným řádkům mezi datovými řádky.
  • pd.json_normalize() zploští vnořený JSON do plochého DataFrame před voláním to_csv() — automaticky zpracovává víceúrovňové vnoření.
  • Předejte index=False do DataFrame.to_csv() — bez toho pandas zapíše nežádoucí sloupec s čísly řádků.
  • Pro soubory nad 500 MB použijte ijson pro streamové parsování JSON v kombinaci s csv.DictWriter pro konstantní využití paměti.

Co je převod JSON na CSV?

Převod JSON na CSV transformuje pole JSON objektů do tabulkového formátu, kde každý objekt se stane řádkem a každý klíč záhlavím sloupce. JSON je hierarchický — objekty mohou být libovolně hluboce vnořeny. CSV je ploché — každá hodnota sedí v mřížce řádků a sloupců. Převod funguje čistě, pokud každý objekt sdílí stejnou sadu klíčů na nejvyšší úrovni. Vnořené objekty, pole a nekonzistentní klíče jsou místem, kde to začíná být zajímavé. Samotná data zůstávají identická; mění se pouze struktura.

Before · json
After · json
[{"order_id":"ord_91a3","total":149.99,"status":"shipped"},
 {"order_id":"ord_b7f2","total":34.50,"status":"pending"}]
order_id,total,status
ord_91a3,149.99,shipped
ord_b7f2,34.50,pending

csv.DictWriter — Převod JSON na CSV bez Pandas

Modul csv je součástí každé instalace Pythonu. Žádný pip install, žádná virtuální prostředí. csv.DictWriter přijme seznam slovníků a zapíše každý z nich jako řádek CSV, přičemž mapuje klíče slovníků na záhlaví sloupců. Parametr fieldnames řídí jak pořadí sloupců, tak které klíče budou zahrnuty.

Python 3.8+ — minimální příklad převodu json na csv
import json
import csv

# Ukázková JSON data — pole objektů objednávek
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

Argument newline="" u funkce open() není na Windows volitelný. Bez něj dostanete dvojité konce řádků — které se v Excelu zobrazí jako prázdné řádky mezi každým datovým řádkem. Na macOS a Linuxu je neškodný, takže jej prostě vždy uvádějte.

Výše uvedený kód používá json.loads() pro řetězec. Použijte json.load() (bez koncového s) při čtení z file handleru. Toto lidi neustále mate — jedna funkce čte řetězec, druhá čte file object.

Python 3.8+ — čtení JSON souboru, zápis CSV souboru
import json
import csv

with open("server_metrics.json", encoding="utf-8") as jf:
    metrics = json.load(jf)  # json.load() pro file objekty

# Explicitní fieldnames řídí pořadí sloupců
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)

# Ve výstupu se objeví pouze pět zadaných sloupců, přesně v tomto pořadí

Nastavení extrasaction="ignore" tiše ignoruje všechny klíče ve slovnících, které nejsou ve vašem seznamu fieldnames. Výchozí hodnota je "raise", která vyvolá ValueError pokud má jakýkoliv slovník neočekávaný klíč. Vyberte si podle toho, jak tolerantní jste k překvapením.

Poznámka:csv.DictWriter vs csv.writer: DictWriter automaticky mapuje klíče slovníků na pozice sloupců. csv.writer zapisuje surové seznamy jako řádky — pořadí sloupců spravujete sami. DictWriter je téměř vždy správná volba pro převod JSON na CSV, protože JSON záznamy jsou již slovníky.

Modul csv v Pythonu obsahuje tři pojmenované dialekty: excel (čárkový oddělovač, konce řádků CRLF — výchozí), excel-tab (tabulátorový oddělovač, konce řádků CRLF) a unix (konce řádků LF, uvozuje všechna nečíselná pole). Předejte název dialektu jako argument dialect do csv.DictWriter. Vlastní dialekt lze také definovat pomocí csv.register_dialect() když váš cílový systém má neobvyklá pravidla uvozování nebo oddělovačů. Pro většinu pracovních postupů JSON na CSV je dialekt excel správný, ale přepněte na unix při zápisu souborů zpracovávaných nástroji POSIX jako awk nebo sort.

Zpracování nestandardních typů: datetime, UUID a Decimal

JSON z API often obsahuje data jako ISO řetězce, UUID jako řetězce s pomlčkami a peněžní hodnoty jako floaty. Když je před zápisem do CSV parsujete do Python objektů za účelem zpracování, musíte je převést zpět na řetězce. Modul csv volá str() na každou hodnotu, takže většina typů prostě funguje. Ale objekty datetime produkují neupravené výchozí řetězcové reprezentace a hodnoty Decimal vyžadují explicitní formátování, aby se předešlo vědecké notaci.

Python 3.8+ — předpřipravení datetime a Decimal před zápisem do CSV
import json
import csv
from datetime import datetime, timezone
from decimal import Decimal
from uuid import UUID

# Simulace parsované odpovědi API s Python typy
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:
    """Převede nestringové typy na řetězce vhodné pro 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

Funkce prepare_row() je zde správným přístupem. Místo toho, abyste se pokoušeli naučit csv.DictWriter o vlastních typech, normalizujete každý záznam na řetězce před zápisem. Preferuji explicitní volání .isoformat() na datetime objektech místo spoléhání na str() — výstupní formát je předvídatelnější a navazující parsery spolehlivě zpracovávají ISO 8601.

Upozornění:Pokud necháte hodnoty Decimal projít bez formátování, velmi malá nebo velmi velká čísla se mohou zobrazit ve vědecké notaci (např. 1.5E+7). Vždy formátujte Decimal s explicitním f-stringem jako f"{value:.2f}" při zápisu finančních dat do CSV.

Alternativní vzor pro pipeline s mnoha vlastními typy je rozšíření json.JSONEncoder. Vytvořte podtřídu, přepište metodu default() tak, aby vracela JSON-serializovatelnou hodnotu pro každý vlastní typ, a poté předejte podtřídu jako argument cls funkci json.dumps(). Překódování přes vlastní encoder před zápisem do CSV normalizuje všechny typy v jednom kroku bez volání prepare_row() pro každý řádek. Vzor prepare_row() ukázaný výše je jednodušší pro jednorázové skripty; přístup s podtřídou JSONEncoder se lépe škáluje, pokud stejný doménový model s vlastními typy sdílí mnoho fází pipeline nebo mikroservis.

Přehled parametrů csv.DictWriter

Úplná signatura konstruktoru je csv.DictWriter(f, fieldnames, restval="", extrasaction="raise", dialect="excel", **fmtparams). Většina z nich má rozumné výchozí hodnoty. Ty, které budete skutečně měnit, jsou fieldnames, delimiter a extrasaction.

Parametr
Typ
Výchozí hodnota
Popis
f
file object
(povinné)
Libovolný objekt s metodou write() — obvykle vrácený funkcí open()
fieldnames
sequence
(povinné)
Seznam klíčů určující pořadí sloupců ve výstupu CSV
restval
str
""
Hodnota zapsaná, pokud slovníku chybí klíč z fieldnames
extrasaction
str
"raise"
"raise" vyvolá ValueError pro extra klíče; "ignore" je tiše ignoruje
dialect
str / Dialect
"excel"
Předdefinovaná pravidla formátování — "excel", "excel-tab" nebo "unix"
delimiter
str
","
Jeden znak oddělující pole — použijte "\t" pro výstup TSV
quotechar
str
"
Znak použitý pro uvozování polí obsahujících oddělovač
quoting
int
csv.QUOTE_MINIMAL
Řídí kdy se uvozování použije — MINIMAL, ALL, NONNUMERIC, NONE
lineterminator
str
"\r\n"
Řetězec připojený za každý řádek — přepište na "\n" pro Unix-style výstup

pandas — Převod JSON na CSV pomocí DataFrame

Pokud již pracujete v kódové základně silně využívající pandas, nebo váš JSON má vnořené objekty, které potřebujete zploštit, je přístup s pandas výrazně méně kódu než verze se stdlib. Kompromis: pandas je závislost o velikosti ~30 MB. Pro jednorázový skript je to v pořádku. Pro Docker image nasazený do produkce je přístup se stdlib lehčí.

Python 3.8+ — pandas read_json a poté to_csv
import pandas as pd

# Přímé načtení JSON pole do DataFrame
df = pd.read_json("warehouse_inventory.json")

# Zápis do CSV — index=False zabraňuje automaticky generovaným číslům řádků
df.to_csv("warehouse_inventory.csv", index=False)

# To je vše. Dva řádky. pandas automaticky odvodí typy sloupců.

Příznak index=False je jedna z těch věcí, které musíte pokaždé vyhledat. Bez něj pandas zapíše sloupec 0, 1, 2, ... jako první sloupec vašeho CSV. To nikdo nechce.

Zploštění vnořeného JSON pomocí json_normalize

Reálné odpovědi API jsou zřídkakdy ploché. Objednávky obsahují dodací adresy, uživatelé obsahují vnořené preference, telemetrické události obsahují vnořená metadata. pd.json_normalize() prochází vnořené slovníky a zploští je do sloupců s tečkami oddělenými názvy.

Python 3.8+ — zploštění vnořeného JSON pomocí 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 zploští vnořené slovníky — sep řídí oddělovač
df = pd.json_normalize(orders, sep="_")
df.to_csv("flat_orders.csv", index=False)

# Výsledné sloupce:
# order_id, placed_at, customer_name, customer_email, customer_tier,
# shipping_method, shipping_address_city, shipping_address_state,
# shipping_address_zip, total

Parametr sep="_" řídí způsob spojování vnořených názvů klíčů. Výchozí hodnota je ".", což produkuje sloupce jako customer.name. Preferuji podtržítka, protože tečky v názvech sloupců způsobují problémy při importech do SQL a v některých vzorcích tabulkových procesorů.

Pro odpovědi API, které obalují pole záznamů pod vnořeným klíčem, použijte parametr record_path. Pokud odpověď vypadá jako {"data": {"orders": [...]}}, předejte record_path=["data", "orders"] pro navigaci ke správnému seznamu. Volitelný parametr meta umožňuje extrahovat pole nadřazené úrovně spolu s vnořenými záznamy — užitečné, když odpověď obsahuje paginační informace nejvyšší úrovně (číslo stránky, celkový počet), které chcete jako sloupec v každém řádku. Společně, record_path a meta zvládají většinu reálných vnořených tvarů API odpovědí bez vlastního předzpracování.

Přehled parametrů DataFrame.to_csv()

DataFrame.to_csv() má přes 20 parametrů. Toto jsou ty, na kterých záleží pro pracovní postupy JSON na CSV.

Parametr
Typ
Výchozí hodnota
Popis
path_or_buf
str / Path / None
None
Cesta k souboru nebo buffer — None vrátí CSV jako řetězec
sep
str
","
Oddělovač polí — použijte "\t" pro TSV
index
bool
True
Zapíše index řádků jako první sloupec — téměř vždy nastavte na False
columns
list
None
Výběr a přeuspořádání sloupců ve výstupu
header
bool / list
True
Zapíše názvy sloupců — nastavte False při přidávání do existujícího souboru
encoding
str
"utf-8"
Výstupní kódování — použijte "utf-8-sig" pro kompatibilitu s Excelem na Windows
na_rep
str
""
Řetězcová reprezentace chybějících hodnot (NaN, None)
quoting
int
csv.QUOTE_MINIMAL
Řídí kdy jsou pole uvozována
Python 3.8+ — to_csv s přepisy běžných parametrů
import pandas as pd

df = pd.read_json("telemetry_events.json")

# Výstup TSV s explicitním kódováním a zpracováním chybějících hodnot
df.to_csv(
    "telemetry_events.tsv",
    sep="\t",
    index=False,
    encoding="utf-8",
    na_rep="NULL",
    columns=["event_id", "timestamp", "source", "severity", "message"],
)

# Zápis na stdout pro přesměrování v shellových skriptech
print(df.to_csv(index=False))

# Vrátit jako řetězec (soubor se nezapíše)
csv_string = df.to_csv(index=False)
print(len(csv_string), "characters")

Převod JSON na CSV ze souboru a odpovědi API

Dva nejčastější reálné scénáře: čtení JSON ze souboru na disku a jeho převod, nebo načtení JSON z HTTP API a uložení výsledku jako CSV. Při vývoji si můžete dovolit vynechat ošetření chyb. V produkci se tato volba stane alertem ve 2 v noci. Soubory nemusí existovat, API mohou vracet stavové kódy 4xx nebo 5xx místo JSON, tělo odpovědi může být chybový objekt namísto pole, nebo může být JSON zkrácen kvůli timeoutu sítě. Níže uvedené vzory explicitně řeší všechny tyto případy, logují chyby na stderr a vracejí počet řádků, aby volající mohl detekovat výstupy s nulovým počtem řádků a odpovídajícím způsobem upozornit.

Soubor na disku — Čtení, převod, uložení

Python 3.8+ — převod JSON souboru na CSV s ošetřením chyb
import json
import csv
import sys

def json_file_to_csv(input_path: str, output_path: str) -> int:
    """Převede JSON soubor obsahující pole objektů na CSV.
    Vrátí počet zapsaných řádků.
    """
    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

    # Shromáždí všechny unikátní klíče ze všech záznamů — zpracovává nekonzistentní schémata
    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")

Odpověď HTTP API — Načtení a převod

Python 3.8+ — načtení JSON z API a uložení jako CSV
import json
import csv
import urllib.request
import urllib.error

def api_response_to_csv(url: str, output_path: str) -> int:
    """Načte JSON z endpointu REST API a zapíše jej jako 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")
Poznámka:Výše uvedený příklad používá urllib ze standardní knihovny, aby byl skript bez závislostí. Pokud máte nainstalovaný requests, nahraďte sekci s urllib za resp = requests.get(url, timeout=30); records = resp.json() — zbytek kódu pro zápis CSV zůstane identický.

Převod JSON na CSV z příkazové řádky

Někdy potřebujete jen jednořádkový příkaz v terminálu. Příznak -c Pythonu vám umožňuje spustit rychlý převod bez vytváření souboru se skriptem. Pro složitější transformace nejprve přesměrujte přes jq pro přetvarování dat a poté převeďte.

bash — jednořádkový převod json na csv
# Python jednořádkový příkaz: čte JSON ze stdin, zapisuje CSV na 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)
"

# Uložení výstupu do souboru
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 — samostatný CLI skript s argparse
# Uložte jako json2csv.py a spusťte: 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 — použití jq + csvkit pro složité transformace
# Instalace csvkit: pip install csvkit

# jq zploští a vybere pole, in2csv zajistí formátování CSV
cat api_response.json | jq '[.[] | {id: .order_id, customer: .customer.name, total}]' | in2csv -f json > orders.csv

# Miller (mlr) je další možnost pro JSON na CSV
mlr --json2csv cat orders.json > orders.csv

Miller (mlr) je samostatný binární soubor, který zachází s JSON, CSV a TSV jako s prvotřídními formáty bez požadavku na Python runtime. Příznak --json2csv převede vstup JSON na CSV v jednom průchodu a můžete řetězit Miller slovesa pro filtrování, řazení nebo přejmenování sloupců ve stejném příkazu před zápisem výstupu. Nainstalujte přes Homebrew na macOS (brew install miller) nebo správce balíčků Linuxu. Je zvláště užitečný v CI pipeline, kde chcete rychlý převod JSON na CSV bez spouštění prostředí Python.

Vysokovýkonná alternativa — pandas s pyarrow

Pro datové sady v řádu desítek milionů řádků čte a zapisuje pandas s backendem pyarrow výrazně rychleji než výchozí nastavení. Engine Arrow podložený C zpracovává sloupcová data efektivněji než modul csv Pythonu pracující řádek po řádku. API zůstává stejné — pouze nastavíte parametr engine.

bash — instalace pyarrow
pip install pyarrow
Python 3.8+ — pandas s pyarrow pro rychlejší zápis CSV
import pandas as pd

# Čtení JSON s enginem pyarrow (rychlejší parsování velkých souborů)
df = pd.read_json("sensor_readings.json", engine="pyarrow")

# to_csv nemá parametr engine, ale DataFrame operace
# mezi čtením a zápisem těží z sloupcového uspořádání pyarrow
df.to_csv("sensor_readings.csv", index=False)

# Pro skutečně velké exporty zvažte zápis do Parquet místo CSV
# — binární formát, 5-10x menší, zachovává typy
df.to_parquet("sensor_readings.parquet", engine="pyarrow")

Pokud zpracováváte více než několik set MB JSON a finální konzument přijímá Parquet, přeskočte CSV úplně. Parquet je menší, zachovává typy sloupců a jak Redshift, tak BigQuery jej nativně načítají. CSV je ztrátový formát — každá hodnota se stane řetězcem.

Výstup v terminálu se zvýrazněním syntaxe

Knihovna rich vykresluje tabulky s ohraničením, zarovnáním a barvami v terminálu — užitečné pro náhled převodu během vývoje bez otevírání výstupního souboru.

bash — instalace rich
pip install rich
Python 3.8+ — náhled výstupu CSV v terminálu pomocí 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)
# Vykreslí barevně zvýrazněnou tabulku s ohraničením v terminálu
Upozornění:Rich je pouze pro zobrazení v terminálu. Nepoužívejte jej pro generování CSV souborů — přidává ANSI escape kódy, které výstup zkorumpují. Zapisujte do souborů pomocí csv.DictWriter nebo DataFrame.to_csv() a rich používejte pouze pro náhledy.

Práce s velkými JSON soubory

json.load() načte celý soubor do paměti. Pro 200 MB JSON soubor to znamená ~200 MB surového textu plus overhead Python objektů — snadno 500 MB+ využití haldy. Pro soubory nad 100 MB streamujte vstup pomocí ijson a zapisujte řádky CSV průběžně.

bash — instalace ijson
pip install ijson

Streamování JSON pole do CSV pomocí ijson

Python 3.8+ — streamování velkého JSON pole do CSV s konstantní pamětí
import ijson
import csv

def stream_json_to_csv(json_path: str, csv_path: str) -> int:
    """Převede velké JSON pole na CSV bez načtení celého souboru do paměti."""
    with open(json_path, "rb") as jf, open(csv_path, "w", newline="", encoding="utf-8") as cf:
        # ijson.items vrací každý prvek pole nejvyšší úrovně postupně
        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 — Jeden objekt na řádek

NDJSON (Newline-Delimited JSON), také nazývaný JSON Lines nebo .jsonl, ukládá jeden platný JSON objekt na řádek bez obalujícího pole. Tento formát je běžný v log pipeline, event streamech (Kafka, Kinesis) a hromadných exportech ze služeb jako Elasticsearch a BigQuery. Protože každý řádek je samostatný JSON objekt, můžete NDJSON soubor zpracovat prostým Python cyklem for přes file handle — není potřeba knihovna ijson. Paměť zůstává konstantní bez ohledu na velikost souboru, což z toho dělá nejjednodušší streamovací přístup, pokud jsou zdrojová data již ve formátu JSON Lines.

Python 3.8+ — převod NDJSON na CSV řádek po řádku
import json
import csv

def ndjson_to_csv(ndjson_path: str, csv_path: str) -> int:
    """Převede soubor JSON oddělený novými řádky na CSV, jeden řádek najednou."""
    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  # přeskočit poškozené řádky

    return count

rows = ndjson_to_csv("access_log.ndjson", "access_log.csv")
print(f"Converted {rows} log entries to CSV")
Poznámka:Přepněte na streamování, když JSON soubor přesáhne 100 MB. 1 GB JSON pole načtené pomocí json.load() může spotřebovat 3–5 GB RAM kvůli overheadu Python objektů. S ijson zůstává paměť konstantní bez ohledu na velikost souboru. Pokud potřebujete jen rychlý převod malého souboru, vložte jej do převodníku JSON na CSV místo toho.

Časté chyby

Chybějící newline='' v open() — prázdné řádky na Windows

Problém: Modul csv zapisuje konce řádků . Bez newline='' přidá Python textový režim na Windows další , čímž vznikne dvojitě řádkovaný výstup.

Řešení: Vždy předávejte newline='' při otevírání souboru pro zápis CSV. Na macOS/Linux je to neškodné.

Before · Python
After · Python
with open("output.csv", "w") as f:
    writer = csv.DictWriter(f, fieldnames=columns)
    writer.writeheader()
    writer.writerows(data)
# Prázdné řádky mezi každým datovým řádkem na Windows
with open("output.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.DictWriter(f, fieldnames=columns)
    writer.writeheader()
    writer.writerows(data)
# Čistý výstup na všech platformách
Zapomenutí index=False v pandas to_csv()

Problém: Bez index=False pandas předřadí sloupec s automaticky rostoucím číslem řádku (0, 1, 2, ...), který CSV znehodnotí daty, jež nebyla v původním JSON.

Řešení: Předejte index=False do to_csv(). Pokud skutečně potřebujete sloupec s indexem, pojmenujte jej explicitně pomocí df.index.name = 'row_num'.

Before · Python
After · Python
df = pd.read_json("events.json")
df.to_csv("events.csv")
# CSV získá extra nepojmenovaný sloupec: ,event_id,timestamp,...
# Počáteční čárka rozbije mnoho CSV parserů
df = pd.read_json("events.json")
df.to_csv("events.csv", index=False)
# Čisté CSV: event_id,timestamp,...
Použití records[0].keys() při nekonzistentních klíčích záznamů

Problém: Pokud JSON objekty mají různé klíče (některé záznamy mají volitelná pole), použití klíčů prvního záznamu jako fieldnames tiše vynechá sloupce, které se vyskytují pouze v pozdějších záznamech.

Řešení: Před vytvořením DictWriteru shromážděte všechny unikátní klíče ze všech záznamů.

Before · Python
After · Python
records = json.load(f)
writer = csv.DictWriter(out, fieldnames=records[0].keys())
# Vynechá pole "discount", které se vyskytuje pouze v records[2]
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="")
# Každý klíč z každého záznamu je zahrnut jako sloupec
Zápis vnořených slovníků přímo do CSV bez zploštění

Problém: csv.DictWriter volá str() na vnořené slovníky, čímž vznikají sloupce s hodnotami jako "{'city': 'Portland'}" — surová Python reprezentace, nikoli skutečná data.

Řešení: Nejprve zploštěte vnořené objekty pomocí pd.json_normalize() nebo vlastní funkce pro zploštění.

Before · Python
After · Python
records = [{"id": "evt_1", "meta": {"source": "web", "region": "us-west"}}]
writer = csv.DictWriter(f, fieldnames=["id", "meta"])
writer.writerows(records)
# sloupec meta obsahuje: {'source': 'web', 'region': 'us-west'}
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)
# Sloupce: id, meta_source, meta_region

csv.DictWriter vs pandas — Rychlé srovnání

Metoda
Vnořený JSON
Vlastní typy
Streaming
Závislosti
Vyžaduje instalaci
csv.DictWriter
✗ (ruční zploštění)
✓ (řádek po řádku)
Žádné
Ne (stdlib)
csv.writer
✓ (řádek po řádku)
Žádné
Ne (stdlib)
pd.DataFrame.to_csv()
✗ (pouze ploché)
✓ (přes dtypes)
pandas + numpy
pip install
pd.json_normalize() + to_csv()
✓ (přes dtypes)
pandas + numpy
pip install
csv.writer + json_flatten
flatten_json
pip install
jq + csvkit (CLI)
✓ (přes jq)
N/A
jq, csvkit
Systémová instalace

Použijte csv.DictWriter když potřebujete nulové závislosti, váš JSON je plochý a skript běží v omezeném prostředí (CI kontejnery, Lambda funkce, embedded Python). Použijte pd.json_normalize() + to_csv() když je JSON vnořený, potřebujete transformovat nebo filtrovat data před exportem, nebo jste již v pandas pracovním postupu. Pro soubory, které se nevejdou do paměti, kombinujte ijson s csv.DictWriter pro streamování s konstantní pamětí.

Pro rychlé konverze bez kódu zvládne převodník JSON na CSV na ToolDeck vše bez jakéhokoli nastavení Pythonu.

Často kladené otázky

Jak převedu JSON na CSV v Pythonu bez pandas?

Použijte vestavěné moduly json a csv. Zavolejte json.load() pro parsování JSON souboru do seznamu slovníků, extrahujte fieldnames z klíčů prvního slovníku, vytvořte csv.DictWriter, zavolejte writeheader() a poté writerows(). Tento přístup nemá žádné externí závislosti a funguje v libovolném prostředí Python 3.x. Běží také rychleji než pandas pro malé soubory, protože nedochází k alokaci DataFrame. Pokud JSON objekty mají v různých záznamech odlišné klíče, nejprve shromážděte všechny unikátní klíče pomocí dict.fromkeys(k for r in records for k in r) před jejich předáním jako fieldnames, abyste předešli chybějícím sloupcům.

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)

Jak zpracovat vnořený JSON při převodu na CSV?

Ploché JSON pole se přímo mapuje na řádky CSV, ale vnořené objekty je třeba nejprve zploštit. S pandas to pd.json_normalize() zvládne automaticky — spojuje vnořené klíče oddělovačem tečky (např. "address.city"). Bez pandas napište rekurzivní funkci, která prochází slovník a spojuje klíče s oddělovačem. Pro hluboce vnořené struktury s více úrovněmi je json_normalize zpracuje najednou. Parametr sep řídí spojovací znak mezi segmenty klíčů — podtržítko je obvykle bezpečnější než výchozí tečka pro importy do SQL a kompatibilitu se vzorci tabulkových procesorů.

Python
import pandas as pd

nested_data = [
    {"id": "ord_91a3", "customer": {"name": "Anna Nováková", "email": "a.novakova@priklad.cz"}},
]
df = pd.json_normalize(nested_data, sep="_")
# Sloupce: id, customer_name, customer_email
df.to_csv("flat_orders.csv", index=False)

Proč má mé CSV na Windows prázdné řádky mezi datovými řádky?

Modul csv zapisuje ve výchozím nastavení konce řádků \r\n. Na Windows otevření souboru v textovém režimu přidá další \r, čímž vznikne \r\r\n — což se zobrazí jako prázdný řádek. Řešením je vždy předat newline="" funkci open(). To říká Pythonu, aby nepřekládal konce řádků a nechal modul csv, aby je spravoval. Tento vzor je vyžadován bez ohledu na operační systém — na macOS a Linuxu je neškodný a na Windows kritický. Dokumentace Pythonu to explicitně uvádí v sekci modulu csv jako správný způsob otevírání souborů pro zápis CSV.

Python
# Špatně — prázdné řádky na Windows
with open("output.csv", "w") as f:
    writer = csv.writer(f)

# Správně — newline="" zabrání dvojitému \r
with open("output.csv", "w", newline="") as f:
    writer = csv.writer(f)

Jak připojím JSON záznamy k existujícímu CSV souboru?

Otevřete soubor v režimu přidávání ("a") a vytvořte DictWriter se stejnými fieldnames. Přeskočte writeheader(), protože řádek záhlaví již existuje. S pandas použijte to_csv(mode="a", header=False). Ujistěte se, že pořadí sloupců odpovídá existujícímu souboru, jinak data skončí ve špatných sloupcích. Pokud si nejste jisti pořadím sloupců v existujícím souboru, nejprve jej otevřete pomocí csv.DictReader a přečtěte fieldnames z jeho atributu fieldnames před vytvořením writeru pro přidávání.

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)

Jaký je nejrychlejší způsob převodu velkého JSON souboru na CSV v Pythonu?

Pro soubory do 500 MB je pd.read_json() následovaný to_csv() nejrychlejším jednokrokovým přístupem — pandas interně používá optimalizovaný kód v C. Pro soubory nad 500 MB použijte ijson pro streamování JSON záznamů a zapište je do CSV pomocí csv.DictWriter řádek po řádku. Tím se využití paměti udržuje konstantní bez ohledu na velikost souboru. Pro soubory NDJSON (jeden JSON objekt na řádek) nepotřebujete ijson vůbec — prostý Python cyklus for přes file handle zpracovává každý řádek nezávisle a dosahuje konstantní paměti bez jakékoli knihovny třetích stran.

Python
# Rychlé pro soubory, které se vejdou do paměti
import pandas as pd
df = pd.read_json("large_dataset.json")
df.to_csv("large_dataset.csv", index=False)

# Streaming pro soubory, které se nevejdou do paměti
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)

Mohu zapsat výstup CSV na stdout místo do souboru v Pythonu?

Ano. Předejte sys.stdout jako file object do csv.writer() nebo csv.DictWriter(). To je užitečné pro přesměrování výstupu v shellových skriptech nebo rychlé ladění. S pandas zavolejte to_csv(sys.stdout, index=False) nebo to_csv(None) pro získání řetězce, který můžete vypsat. Není potřeba žádný dočasný soubor. Při zápisu na stdout na Windows nejprve zavolejte sys.stdout.reconfigure(newline=""), abyste se vyhnuli problému s dvojitým návratem vozíku, protože stdout se standardně otevírá v textovém režimu.

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

Související nástroje

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 SharmaTechnický recenzent

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.