JSON till CSV i Python — DictWriter + pandas Exempel

·Backend Developer·Granskad avPriya Sharma·Publicerad

Använd det kostnadsfria JSON to CSV direkt i webbläsaren — ingen installation krävs.

Prova JSON to CSV online →

Nästan varje datapipeline träffar förr eller senare samma steg: ett API returnerar JSON, men nästa konsument — ett kalkylblad, ett importskript, ett Redshift COPY-kommando — behöver CSV. Att konvertera JSON till CSV i Python låter enkelt tills du stöter på nästlade objekt, inkonsistenta nycklar eller datetime-värden som behöver särskild hantering. Python erbjuder två solida vägar: de inbyggda json + csv modulerna för skript utan externa beroenden, och pandas för nästlad platning och större datamängder — eller den online-konverteraren för JSON till CSV för snabba engångskönverteringar utan kod. Den här guiden täcker båda metoderna från början till slut, med körbara Python 3.8+-exempel.

  • csv.DictWriter konverterar en lista med dicts till CSV utan externa beroenden — använd json.load() för tolkning, sedan writeheader() + writerows().
  • Öppna alltid CSV-filer med newline="" på Windows för att undvika tomma rader mellan datarader.
  • pd.json_normalize() plattar nästlad JSON till en platt DataFrame innan to_csv() anropas — hanterar flerniväsnästling automatiskt.
  • Skicka index=False till DataFrame.to_csv() — utan det skriver pandas en oönskad radnummerkolumn.
  • För filer över 500 MB, använd ijson för strömning av JSON-tolkning kombinerat med csv.DictWriter för konstant minnesanvändning.

Vad är JSON till CSV-konvertering?

JSON till CSV-konvertering omvandlar en array av JSON-objekt till ett tabellformat där varje objekt blir en rad och varje nyckel blir en kolumnrubrik. JSON är hierarkiskt — objekt kan vara nästlade godtyckligt djupt. CSV är platt — varje värde sitter i ett rad-kolumnnätverk. Konverteringen fungerar smidigt när alla objekt delar samma uppsättning nycklar på toppnivå. Nästlade objekt, arrayer och inkonsistenta nycklar är där det blir intressant. Rådata förblir identisk; bara strukturen förändras.

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 — Konvertera JSON till CSV utan pandas

Modulen csv följer med varje Python-installation. Ingen pip install, inga krångel med virtuella miljöer. csv.DictWriter tar en lista med dictionaries och skriver var och en som en CSV-rad, och mappar dict-nycklar till kolumnrubriker. Parametern fieldnames styr både kolumnordningen och vilka nycklar som inkluderas.

Python 3.8+ — minimalt json till csv-exempel
import json
import csv

# Exempel på JSON-data — en array med orderobjekt
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

Argumentet newline="" open() är inte valfritt på Windows. Utan det får du dubbla vagnreturer — som visas som tomma rader mellan varje datarad i Excel. På macOS och Linux är det ofarligt, så inkludera det alltid.

Koden ovan använder json.loads() för en sträng. Använd json.load() (utan avslutande s) när du läser från ett filhandtag. Detta förvirrar folk hela tiden — den ena läser en sträng, den andra läser ett filobjekt.

Python 3.8+ — läs JSON-fil, skriv CSV-fil
import json
import csv

with open("server_metrics.json", encoding="utf-8") as jf:
    metrics = json.load(jf)  # json.load() för filobjekt

# Explicita fieldnames styr kolumnordningen
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)

# Endast de fem angivna kolumnerna visas, i exakt den ordningen

Att sätta extrasaction="ignore" ignorerar tyst alla nycklar i dictar som inte finns i din fieldnames-lista. Standardvärdet är "raise", som kastar ett ValueError om någon dict har en oväntad nyckel. Välj det som passar din tolerans för överraskningar.

Obs:csv.DictWriter vs csv.writer: DictWriter mappar dict-nycklar till kolumnpositioner automatiskt. csv.writer skriver rålistor som rader — du hanterar kolumnordningen själv. DictWriter är nästan alltid rätt val för JSON-till-CSV eftersom JSON-poster redan är dictionaries.

Pythons csv modul levereras med tre namngivna dialekter: excel (kommaavgränsare, CRLF-radslut — standard), excel-tab (tabb-avgränsare, CRLF-radslut), och unix (LF-radslut, citerar alla icke-numeriska fält). Skicka dialektnamnet som dialect -argument till csv.DictWriter. Du kan också definiera en anpassad dialekt med csv.register_dialect() när ditt målsystem har ovanliga citerings- eller avgränsarregler. För de flesta JSON-till-CSV-arbetsflöden är excel dialekten korrekt, men byt till unix när du skriver filer som ska bearbetas av POSIX-verktyg som awk eller sort.

Hantera icke-standardtyper: datetime, UUID och Decimal

JSON från API:er innehåller ofta datum som ISO-strängar, UUID:er som streckade strängar, och monetära värden som floats. När du tolkar dessa till Python-objekt för bearbetning innan CSV-skrivning, behöver du konvertera dem tillbaka till strängar. Modulen csv anropar str() på varje värde, så de flesta typer fungerar direkt. Men datetime-objekt ger röriga standardsträngrepresentationer, och Decimal-värden behöver explicit formatering för att undvika vetenskaplig notation.

Python 3.8+ — förbearbeta datetime och Decimal innan CSV-skrivning
import json
import csv
from datetime import datetime, timezone
from decimal import Decimal
from uuid import UUID

# Simulerar tolkad API-respons med Python-typer
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:
    """Konvertera icke-strängtyper till CSV-vänliga strängar."""
    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

Funktionen prepare_row() är rätt tillvägagångssätt här. Istället för att försöka lära csv.DictWriter om anpassade typer, normaliserar du varje post till strängar innan skrivning. Jag föredrar att anropa .isoformat() explicit på datetime-objekt istället för att förlita sig på str() — utdataformatet är mer förutsägbart, och nedströms tolkare hanterar ISO 8601 pålitligt.

Varning:Om du låter Decimal-värden passera utan formatering kan mycket små eller mycket stora tal renderas i vetenskaplig notation (t.ex. 1.5E+7). Formatera alltid Decimal med en explicit f-sträng som f"{value:.2f}" när du skriver finansiella data till CSV.

Ett alternativt mönster för pipelines med många anpassade typer är att utöka json.JSONEncoder. Skapa en underklass, åsidosätt default() -metoden för att returnera ett JSON-serialiserbart värde för varje anpassad typ, och skicka sedan underklassen som cls -argument till json.dumps(). Omkodning via den anpassade kodaren innan CSV-skrivning normaliserar alla typer i ett steg utan ett per-rad prepare_row() -anrop. Mönstret prepare_row() ovan är enklare för engångsskript; JSONEncoder-underklassmetoden skalar bättre när samma domänmodell med anpassade typer delas mellan många pipeline-steg eller mikrotjänster.

csv.DictWriter — Parameterreferens

Den fullständiga konstruktorsignaturen är csv.DictWriter(f, fieldnames, restval="", extrasaction="raise", dialect="excel", **fmtparams). De flesta av dessa har vettiga standardvärden. De du faktiskt kommer att ändra är fieldnames, delimiter, och extrasaction.

Parameter
Typ
Standard
Beskrivning
f
filobjekt
(obligatorisk)
Valfritt objekt med en write()-metod — vanligtvis från open()
fieldnames
sekvens
(obligatorisk)
Lista med nycklar som styr kolumnordningen i CSV-utdata
restval
str
""
Värde som skrivs när en dict saknar en nyckel från fieldnames
extrasaction
str
"raise"
"raise" kastar ValueError vid extra nycklar; "ignore" ignorerar dem tyst
dialect
str / Dialect
"excel"
Fördefinierade formateringsregler — "excel", "excel-tab" eller "unix"
delimiter
str
","
Enkelt tecken som separerar fält — använd "\t" för TSV-utdata
quotechar
str
"
Tecken som används för att citera fält som innehåller avgränsaren
quoting
int
csv.QUOTE_MINIMAL
Styr när citering tillämpas — MINIMAL, ALL, NONNUMERIC, NONE
lineterminator
str
"\r\n"
Sträng som läggs till efter varje rad — åsidosätt med "\n" för Unix-stil

pandas — Konvertera JSON till CSV med DataFrames

Om du redan arbetar i en pandas-tung kodbas, eller din JSON har nästlade objekt som du behöver platta ut, är pandas-metoden betydligt kortare kod än stdlib-versionen. Avvägningen: pandas är ett ~30 MB-beroende. För ett engångsskript är det okej. För en Docker-avbildning du skickar till produktion håller stdlib-metoden saker lättare.

Python 3.8+ — pandas read_json sedan to_csv
import pandas as pd

# Läs JSON-array direkt till en DataFrame
df = pd.read_json("warehouse_inventory.json")

# Skriv till CSV — index=False förhindrar auto-genererade radnummer
df.to_csv("warehouse_inventory.csv", index=False)

# Det är allt. Två rader. pandas härleder kolumntyper automatiskt.

Flaggan index=False är en av de saker du letar upp varje enskild gång. Utan den skriver pandas en 0, 1, 2, ... kolumn som den första kolumnen i din CSV. Ingen vill ha det.

Platta nästlad JSON med json_normalize

Riktiga API-svar är sällan platta. Beställningar innehåller leveransadresser, användare innehåller nästlade inställningar, telemetrihändelser innehåller nästlad metadata. pd.json_normalize() traverserar nästlade dictionaries och plattar dem till kolumner med punktseparerade namn.

Python 3.8+ — platta nästlad JSON med 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 plattar nästlade dicts — sep styr avgränsaren
df = pd.json_normalize(orders, sep="_")
df.to_csv("flat_orders.csv", index=False)

# Resulterande kolumner:
# order_id, placed_at, customer_name, customer_email, customer_tier,
# shipping_method, shipping_address_city, shipping_address_state,
# shipping_address_zip, total

Parametern sep="_" styr hur nästlade nyckelnamn fogas ihop. Standardvärdet är ".", vilket ger kolumner som customer.name. Jag föredrar understreck eftersom punkter i kolumnnamn ställer till problem med SQL-import och vissa kalkylbladsformler.

För API-svar som omsluter poster-arrayen under en nästlad nyckel, använd parametern record_path. Om svaret ser ut som {"data": {"orders": [...]}}, skicka record_path=["data", "orders"] för att navigera till rätt lista. Den valfria meta -parametern låter dig dra in fält från föräldranivån bredvid de nästlade posterna — användbart när svaret inkluderar toppnivåpagineringsinformation (sidnummer, totalt antal) som du vill ha som en kolumn i varje rad. Tillsammans hanterar record_path och meta de flesta verkliga nästlade API-svarsformer utan anpassad förbearbetning.

DataFrame.to_csv() — Parameterreferens

DataFrame.to_csv() har över 20 parametrar. Dessa är de som spelar roll för JSON-till-CSV-arbetsflöden.

Parameter
Typ
Standard
Beskrivning
path_or_buf
str / Path / None
None
Filsökväg eller buffert — None returnerar CSV som en sträng
sep
str
","
Fältavgränsare — använd "\t" för TSV
index
bool
True
Skriv radindex som första kolumn — sätt nästan alltid till False
columns
list
None
Välj ut och ordna om kolumner i utdata
header
bool / list
True
Skriv kolumnnamn — sätt False vid tillägg till befintlig fil
encoding
str
"utf-8"
Utdatakodning — använd "utf-8-sig" för Excel-kompatibilitet på Windows
na_rep
str
""
Strängrepresentation för saknade värden (NaN, None)
quoting
int
csv.QUOTE_MINIMAL
Styr när fält citeras
Python 3.8+ — to_csv med vanliga parameteråsidosättningar
import pandas as pd

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

# TSV-utdata med explicit kodning och hantering av saknade värden
df.to_csv(
    "telemetry_events.tsv",
    sep="\t",
    index=False,
    encoding="utf-8",
    na_rep="NULL",
    columns=["event_id", "timestamp", "source", "severity", "message"],
)

# Skriv till stdout för piping i skalskript
print(df.to_csv(index=False))

# Returnera som sträng (ingen fil skrivs)
csv_string = df.to_csv(index=False)
print(len(csv_string), "tecken")

Konvertera JSON från fil och API-svar

De två vanligaste scenarierna i verkligheten: läsa JSON från en fil på disk och konvertera den, eller hämta JSON från ett HTTP-API och spara resultatet som CSV. Under utveckling kan du klara dig utan felhantering. I produktion blir det valet ett larm kl. 02 på natten. Filer kanske inte finns, API:er kanske returnerar 4xx- eller 5xx-statuskoder istället för JSON, svarskroppen kanske är ett felobjekt snarare än en array, eller JSON kan vara avkortat på grund av ett nätverkstimeout. Mönstren nedan hanterar alla dessa fall explicit, loggar fel till stderr och returnerar ett radantal så att anropare kan upptäcka nollradsutdata och larma därefter.

Fil på disk — läs, konvertera, spara

Python 3.8+ — konvertera JSON-fil till CSV med felhantering
import json
import csv
import sys

def json_file_to_csv(input_path: str, output_path: str) -> int:
    """Konvertera en JSON-fil innehållande en array av objekt till CSV.
    Returnerar antalet skrivna rader.
    """
    try:
        with open(input_path, encoding="utf-8") as jf:
            data = json.load(jf)
    except FileNotFoundError:
        print(f"Fel: {input_path} hittades inte", file=sys.stderr)
        return 0
    except json.JSONDecodeError as exc:
        print(f"Fel: ogiltig JSON i {input_path}: {exc.msg} på rad {exc.lineno}", file=sys.stderr)
        return 0

    if not isinstance(data, list) or not data:
        print(f"Fel: förväntade en icke-tom JSON-array i {input_path}", file=sys.stderr)
        return 0

    # Samla in alla unika nycklar över alla poster — hanterar inkonsistenta scheman
    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"Skrev {rows} rader till deploy_logs.csv")

HTTP API-svar — hämta och konvertera

Python 3.8+ — hämta JSON från API och spara som CSV
import json
import csv
import urllib.request
import urllib.error

def api_response_to_csv(url: str, output_path: str) -> int:
    """Hämta JSON från en REST API-endpoint och skriv det som 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"Fel: API returnerade status {resp.status}")
                return 0
            body = resp.read().decode("utf-8")
    except urllib.error.URLError as exc:
        print(f"Fel: kunde inte nå {url}: {exc.reason}")
        return 0

    try:
        records = json.loads(body)
    except json.JSONDecodeError as exc:
        print(f"Fel: API returnerade ogiltig JSON: {exc.msg}")
        return 0

    if not isinstance(records, list) or not records:
        print("Fel: förväntade en icke-tom JSON-array från API:et")
        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"Exporterade {rows} driftsättningar till CSV")
Obs:Exemplet ovan använder urllib från standardbiblioteket för att hålla skriptet beroendenfritt. Om du har requests installerat, ersätt urllib-delen med resp = requests.get(url, timeout=30); records = resp.json() — resten av CSV-skrivningskoden förblir identisk.

JSON till CSV-konvertering via kommandoraden

Ibland behöver du bara en one-liner i terminalen. Pythons -c -flagga låter dig köra en snabb konvertering utan att skapa en skriptfil. För mer komplexa omvandlingar, pixa genom jq först för att omforma data, och konvertera sedan.

bash — one-liner för json till csv-konvertering
# Python one-liner: läser JSON från stdin, skriver CSV till 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)
"

# Spara utdata till en fil
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 — fristående CLI-skript med argparse
# Spara som json2csv.py och kör: 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 — använda jq + csvkit för komplexa omvandlingar
# Installera csvkit: pip install csvkit

# jq plattar och väljer fält, in2csv hanterar CSV-formateringen
cat api_response.json | jq '[.[] | {id: .order_id, customer: .customer.name, total}]' | in2csv -f json > orders.csv

# Miller (mlr) är ett annat alternativ för JSON-till-CSV
mlr --json2csv cat orders.json > orders.csv

Miller (mlr) är ett fristående binärt program som behandlar JSON, CSV och TSV som förstklassiga format utan Python-körtid. Flaggan --json2csv konverterar JSON-indata till CSV i ett enda pass, och du kan kedja Miller-verb för att filtrera, sortera eller byta namn på kolumner i samma kommando innan utdata skrivs. Installera via Homebrew på macOS (brew install miller) eller din Linux-pakethanterare. Det är särskilt användbart i CI-pipelines där du vill ha snabb JSON-till-CSV-konvertering utan att starta upp en Python-miljö.

Högprestandaalternativ — pandas med pyarrow

För datamängder i storleksordningen tiotals miljoner rader läser och skriver pandas med bakänden pyarrow betydligt snabbare än standardvarianten. Den C-baserade Arrow-motorn bearbetar kolumndata mer effektivt än Pythons rad-för-rad csv-modul. API:et är detsamma — du sätter bara motorparametern.

bash — installera pyarrow
pip install pyarrow
Python 3.8+ — pandas med pyarrow för snabbare CSV-skrivning
import pandas as pd

# Läs JSON med pyarrow-motorn (snabbare tolkning för stora filer)
df = pd.read_json("sensor_readings.json", engine="pyarrow")

# to_csv har ingen motorparameter, men DataFrame-operationerna
# mellan läsning och skrivning drar nytta av pyarrows kolumnlayout
df.to_csv("sensor_readings.csv", index=False)

# För riktigt stora exporter, överväg att skriva till Parquet istället för CSV
# — binärt format, 5-10x mindre, bevarar typer
df.to_parquet("sensor_readings.parquet", engine="pyarrow")

Om du bearbetar mer än några hundra MB JSON och den slutliga konsumenten accepterar Parquet, hoppa över CSV helt. Parquet är mindre, bevarar kolumntyper, och både Redshift och BigQuery laddar det inbyggt. CSV är ett förlustformat — varje värde blir en sträng.

Terminalutdata med syntaxmarkering

Biblioteket rich renderar tabeller med kanter, justering och färg i terminalen — användbart för att förhandsgranska en konvertering under utveckling utan att öppna utdatafilen.

bash — installera rich
pip install rich
Python 3.8+ — förhandsgranska CSV-utdata i terminalen med 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="Förhandsgranskning av servermätvärden", 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)
# Renderar en färgmarkerad tabell med kanter i terminalen
Varning:Rich är endast för terminalvisning. Använd det inte för att generera CSV-filer — det lägger till ANSI-escape-koder som korrupterar utdata. Skriv till filer med csv.DictWriter eller DataFrame.to_csv(), och använd rich endast för förhandsgranskning.

Arbeta med stora JSON-filer

json.load() läser hela filen till minnet. För en 200 MB JSON-fil innebär det ~200 MB råtext plus Python-objektets overhead — enkelt 500 MB+ heap-användning. För filer över 100 MB, strömma indata med ijson och skriv CSV-rader allteftersom.

bash — installera ijson
pip install ijson

Strömma JSON-array till CSV med ijson

Python 3.8+ — strömma stor JSON-array till CSV med konstant minne
import ijson
import csv

def stream_json_to_csv(json_path: str, csv_path: str) -> int:
    """Konvertera en stor JSON-array till CSV utan att läsa in allt i minnet."""
    with open(json_path, "rb") as jf, open(csv_path, "w", newline="", encoding="utf-8") as cf:
        # ijson.items ger varje element i den topplevelarray ett i taget
        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"Strömmade {rows} poster till CSV")

NDJSON / JSON Lines — ett objekt per rad

NDJSON (Newline-Delimited JSON), även kallat JSON Lines eller .jsonl, lagrar ett giltigt JSON-objekt per rad utan omslutande array. Det här formatet är vanligt i logg-pipelines, händelseströmmar (Kafka, Kinesis), och massexporter från tjänster som Elasticsearch och BigQuery. Eftersom varje rad är ett fristående JSON-objekt kan du bearbeta en NDJSON-fil med en vanlig Python for -loop över filhandtaget — inget behov av ijson-biblioteket. Minnet förblir konstant oavsett filstorlek, vilket gör detta till den enklaste strömningsmetoden när källdata redan är i JSON Lines-format.

Python 3.8+ — konvertera NDJSON till CSV rad för rad
import json
import csv

def ndjson_to_csv(ndjson_path: str, csv_path: str) -> int:
    """Konvertera en nyradsavgränsad JSON-fil till CSV, en rad i taget."""
    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  # hoppa över felaktiga rader

    return count

rows = ndjson_to_csv("access_log.ndjson", "access_log.csv")
print(f"Konverterade {rows} loggposter till CSV")
Obs:Byt till strömning när JSON-filen överstiger 100 MB. En 1 GB JSON-array laddad med json.load() kan förbruka 3–5 GB RAM på grund av Python-objektets overhead. Med ijson förblir minnet konstant oavsett filstorlek. Om du bara behöver en snabb konvertering av en liten fil, klistra in den i JSON till CSV-konverteraren istället.

Vanliga misstag

Saknar newline='' i open() — tomma rader på Windows

Problem: csv-modulen skriver \r\n radslut. Utan newline='' lägger Pythons textläge till ytterligare ett \r på Windows, vilket ger dubbelt radavstånd.

Lösning: Skicka alltid newline='' när du öppnar en fil för CSV-skrivning. Det är ofarligt på macOS/Linux.

Before · Python
After · Python
with open("output.csv", "w") as f:
    writer = csv.DictWriter(f, fieldnames=columns)
    writer.writeheader()
    writer.writerows(data)
# Tomma rader mellan varje datarad på Windows
with open("output.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.DictWriter(f, fieldnames=columns)
    writer.writeheader()
    writer.writerows(data)
# Ren utdata på alla plattformar
Glömmer index=False i pandas to_csv()

Problem: Utan index=False lägger pandas till en auto-inkrementerad radnummerkolumn (0, 1, 2, ...) som förorenar CSV:en med data som aldrig fanns i den ursprungliga JSON:en.

Lösning: Skicka index=False till to_csv(). Om du faktiskt behöver en indexkolumn, namnge den explicit med df.index.name = 'row_num'.

Before · Python
After · Python
df = pd.read_json("events.json")
df.to_csv("events.csv")
# CSV får en extra namnlös kolumn: ,event_id,timestamp,...
# Det inledande kommatecknet bryter många CSV-tolkare
df = pd.read_json("events.json")
df.to_csv("events.csv", index=False)
# Ren CSV: event_id,timestamp,...
Använder records[0].keys() när poster har inkonsistenta nycklar

Problem: Om JSON-objekt har olika nycklar (vissa poster har valfria fält), ger användning av den första postens nycklar som fieldnames tyst bort kolumner som bara visas i senare poster.

Lösning: Samla in alla unika nycklar över alla poster innan du skapar DictWriter.

Before · Python
After · Python
records = json.load(f)
writer = csv.DictWriter(out, fieldnames=records[0].keys())
# Missar fältet "discount" som bara visas i 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="")
# Varje nyckel från varje post inkluderas som kolumn
Skriver nästlade dicts direkt till CSV utan platning

Problem: csv.DictWriter anropar str() på nästlade dicts, vilket ger kolumner med värden som "{'city': 'Portland'}"— rå Python repr, inte faktisk data.

Lösning: Platta nästlade objekt först med pd.json_normalize() eller en anpassad platningsfunktion.

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

csv.DictWriter vs pandas — Snabb jämförelse

Metod
Nästlad JSON
Anpassade typer
Strömning
Beroenden
Kräver installation
csv.DictWriter
✗ (manuell platning)
✓ (rad för rad)
Inga
Nej (stdlib)
csv.writer
✓ (rad för rad)
Inga
Nej (stdlib)
pd.DataFrame.to_csv()
✗ (endast platt)
✓ (via dtypes)
pandas + numpy
pip install
pd.json_normalize() + to_csv()
✓ (via dtypes)
pandas + numpy
pip install
csv.writer + json_flatten
flatten_json
pip install
jq + csvkit (CLI)
✓ (via jq)
N/A
jq, csvkit
Systeminstallation

Använd csv.DictWriter när du behöver noll beroenden, din JSON är platt och skriptet körs i en begränsad miljö (CI-containrar, Lambda-funktioner, inbäddad Python). Använd pd.json_normalize() + to_csv() när JSON:en är nästlad, du behöver omvandla eller filtrera data före export, eller du redan befinner dig i ett pandas-arbetsflöde. För filer som inte ryms i minnet, kombinera ijson med csv.DictWriter för konstant minnesströmning.

För snabba konverteringar utan kod hanterar JSON till CSV-konverteraren på ToolDeck det utan någon Python-installation.

Vanliga frågor

Hur konverterar jag JSON till CSV i Python utan pandas?

Använd de inbyggda modulerna json och csv. Anropa json.load() för att tolka JSON-filen till en lista med dicts, extrahera fieldnames från den första dictens nycklar, skapa en csv.DictWriter, anropa writeheader() och sedan writerows(). Den här metoden har noll externa beroenden och fungerar i alla Python 3.x-miljöer. Den körs också snabbare än pandas för små filer eftersom det inte sker någon DataFrame-allokering. Om dina JSON-objekt har inkonsistenta nycklar mellan poster, samla in alla unika nycklar först med dict.fromkeys(k for r in records for k in r) innan du skickar dem som fieldnames för att undvika saknade kolumner.

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)

Hur hanterar jag nästlad JSON vid konvertering till CSV?

Platta JSON-arrayer mappas direkt till CSV-rader, men nästlade objekt behöver plattas ut först. Med pandas hanterar pd.json_normalize() detta automatiskt — den fogar ihop nästlade nycklar med en punkt som separator (t.ex. "address.city"). Utan pandas, skriv en rekursiv funktion som traverserar dicten och sammanfogar nycklar med en avgränsare. För djupt nästlade strukturer med flera nivåer hanterar json_normalize dem alla i ett enda anrop. Parametern sep styr tecknet som fogar ihop nyckelsegment — understreck är vanligtvis säkrare än standardpunkten för SQL-import och kompatibilitet med kalkylbladsformler.

Python
import pandas as pd

nested_data = [
    {"id": "ord_91a3", "customer": {"name": "Anna Lindqvist", "email": "a.lindqvist@exempel.se"}},
]
df = pd.json_normalize(nested_data, sep="_")
# Kolumner: id, customer_name, customer_email
df.to_csv("flat_orders.csv", index=False)

Varför har min CSV tomma rader mellan datarader på Windows?

csv-modulen skriver \r\n radslut som standard. På Windows lägger öppning av filen i textläge till ytterligare ett \r, vilket ger \r\r\n — som visas som en tom rad. Lösningen är att alltid skicka newline="" till open(). Det talar om för Python att inte översätta radslut, och låter csv-modulen hantera dem. Detta mönster krävs oavsett operativsystem — det är ofarligt på macOS och Linux, och kritiskt på Windows. Python-dokumentationen tar uttryckligen upp detta i csv-modulens avsnitt som det korrekta sättet att öppna filer för CSV-skrivning.

Python
# Fel — tomma rader på Windows
with open("output.csv", "w") as f:
    writer = csv.writer(f)

# Rätt — newline="" förhindrar dubbla \r
with open("output.csv", "w", newline="") as f:
    writer = csv.writer(f)

Hur lägger jag till JSON-poster i en befintlig CSV-fil?

Öppna filen i tilläggsläge ("a") och skapa en DictWriter med samma fieldnames. Hoppa över writeheader() eftersom rubrikraden redan finns. Med pandas, använd to_csv(mode="a", header=False). Se till att kolumnordningen matchar den befintliga filen, annars hamnar data i fel kolumner. Om du är osäker på kolumnordningen i den befintliga filen, öppna den först med csv.DictReader och läs fieldnames från dess fieldnames-attribut innan du skapar skrivaren för tillägg.

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)

Vad är det snabbaste sättet att konvertera en stor JSON-fil till CSV i Python?

För filer under 500 MB är pd.read_json() följt av to_csv() det snabbaste enskilda anropet — pandas använder optimerad C-kod internt. För filer över 500 MB, använd ijson för att strömma JSON-poster och skriv dem till CSV med csv.DictWriter rad för rad. Detta håller minnesanvändningen konstant oavsett filstorlek. För NDJSON-filer (ett JSON-objekt per rad) behöver du inte ijson alls — en vanlig Python for-loop över filhandtaget bearbetar varje rad oberoende och uppnår konstant minne utan något tredjepartsbibliotek.

Python
# Snabbt för filer som ryms i minnet
import pandas as pd
df = pd.read_json("large_dataset.json")
df.to_csv("large_dataset.csv", index=False)

# Strömning för filer som inte ryms i minnet
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)

Kan jag skriva CSV-utdata till stdout istället för en fil i Python?

Ja. Skicka sys.stdout som filobjektet till csv.writer() eller csv.DictWriter(). Detta är användbart för att pipa utdata i skalskript eller snabb felsökning. Med pandas, anropa to_csv(sys.stdout, index=False) eller to_csv(None) för att få en sträng du kan skriva ut. Ingen temporär fil behövs. Vid skrivning till stdout på Windows, anropa sys.stdout.reconfigure(newline="") först för att undvika problemet med dubbel vagnretur, eftersom stdout öppnas i textläge som standard.

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

Relaterade verktyg

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 SharmaTeknisk granskare

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.