Skip to content
shellmap

Convert a CSV file to JSON

Parse a CSV (with header row) and emit an array of JSON objects keyed by header.

How to convert a csv file to json in each shell

Bashunix
python3 -c "import csv, json, sys; print(json.dumps([dict(r) for r in csv.DictReader(sys.stdin)]))" < data.csv

Python `csv.DictReader` parses RFC 4180 correctly (quoted-field-with-embedded-commas, escaped quotes `""` → `"`). One-line jq-only alternative for SIMPLE CSV (no quoted commas): `jq -Rsn '[inputs / "\n" | .[1:] | map(split(","))]'` — but it BREAKS on real-world CSV. For production scripts use Python or `mlr` (Miller).

Zshunix
python3 -c "import csv, json, sys; print(json.dumps(list(csv.DictReader(sys.stdin))))" < data.csv

Same Python idiom. macOS ships Python 3 by default since 12. Note `csv.DictReader` returns ordered-dict items (insertion order matches CSV column order). For UTF-8 CSV with BOM: `csv.DictReader(open("f.csv", encoding="utf-8-sig"))` strips the BOM.

Fishunix
python3 -c "import csv, json, sys; print(json.dumps(list(csv.DictReader(sys.stdin))))" < data.csv

Same Python. Fish-friendly capture: `set -l json (python3 -c "..." < data.csv)`. The `jq` one-liner alternative is fragile on quoted-comma CSVs — accept the Python dependency.

PowerShellwindows
Import-Csv data.csv | ConvertTo-Json

pwsh `Import-Csv` parses RFC 4180 natively — handles quoted-fields-with-commas, escaped quotes, line breaks inside quoted fields. The one-liner is true cross-platform on pwsh (Windows / Linux / macOS). `-Delimiter ";"` for semicolon-separated; `-Header "Col1","Col2"` if the CSV has no header row. Pipe to `ConvertTo-Json -Depth 10` for nested structures.

cmd.exewindows
powershell -Command "Import-Csv data.csv | ConvertTo-Json"

cmd has no native CSV/JSON support. Shell out to pwsh, which is built into Windows 10+. For a Python-only environment without pwsh: `python -c "..."` (same Python one-liner as bash) works in cmd too since Windows 10/11 has the Python launcher.

Equivalents listed for Bash, Zsh, Fish, PowerShell, cmd.exe.

Gotchas & notes

  • **Quoted fields with embedded commas — the killer trap**: real-world CSVs have rows like `"Smith, John",30,NYC` where the first field contains a comma. Naive splitters (`awk -F,`, `cut -d,`, `column -t -s,`, jq `split(",")`) break this row into 4 fields instead of 3. RFC 4180 dictates that fields with commas / quotes / newlines are double-quoted, and literal quotes inside are doubled (`""`). Use a real CSV parser: pwsh `Import-Csv`, Python `csv` module, Miller `mlr`, `csvkit` (`csvjson data.csv`). Do NOT roll your own.
  • **UTF-8 BOM**: CSV files exported from Excel often start with the bytes `0xEF 0xBB 0xBF` (UTF-8 BOM). Python `csv.DictReader` reads the BOM as part of the first header name — so `data["\ufeffName"]` instead of `data["Name"]`. Open with `encoding="utf-8-sig"` to strip. pwsh `Import-Csv` handles BOM automatically on pwsh 7+; pwsh 5.1 needs `Get-Content -Encoding UTF8 | ConvertFrom-Csv`.
  • **Header row vs no-header**: `Import-Csv` (pwsh) assumes ROW 1 is headers. If the CSV has no headers, use `Import-Csv -Header "Col1","Col2","Col3"`. Python `csv.DictReader` similarly assumes row 1; for no-header CSVs use `csv.reader` (list-of-lists). jq has no header concept — must hand-roll.
  • **Type coercion**: `Import-Csv` returns ALL columns as strings (`"30"`, not `30`). For typed JSON (numbers, booleans), post-process: `Import-Csv data.csv | ForEach-Object { $_.Age = [int]$_.Age; $_ } | ConvertTo-Json`. Python `csv.DictReader` is also string-only — cast in code. Miller `mlr` auto-detects types (`mlr --icsv --ojson cat data.csv`).

Related commands

Related tasks