JSON do CSV v Pythonu — Příklady DictWriter a pandas
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.
[{"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.
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.95Argument 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.
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.
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.
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 GmbHFunkce 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.
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.
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čí.
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.
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, totalParametr 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.
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í
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
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")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.
# 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
# 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)
" "$@"# 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.csvMiller (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.
pip install pyarrow
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.
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)
# Vykreslí barevně zvýrazněnou tabulku s ohraničením v terminálucsv.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ě.
pip install ijson
Streamování JSON pole do CSV pomocí ijson
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.
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")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
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é.
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 Windowswith 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áchProblé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'.
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,...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ů.
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
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í.
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_regioncsv.DictWriter vs pandas — Rychlé srovnání
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.
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ů.
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.
# Š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í.
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.
# 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.
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.1Související nástroje
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.