Skip to content
Commitpedia
Log in Join & edit

CSV to JSON converter

A small command-line tool that turns a CSV file into a JSON array of objects, with optional number detection, custom delimiters and output to a file.

Not checked by a trusted editor yet Last edited Outdated?

Edit history of CSV to JSON converter: 1 recorded edit
Edit history · 1 edit
Type
Script
Edits
1
Editors
1
First issued
15 Oct 2026
Last edit
15 Oct 2026
Language
python
Licence
CC0-1.0

What this changes

Without -o it is read-only: it reads the CSV file and prints JSON. With -o FILE it creates or overwrites that one JSON file. Nothing else on your system is changed.

How to undo it

Without -o, nothing to undo. With -o, delete the output, e.g. rm people.json. An existing file at that path is overwritten, so pick a new name or copy it first.

Spreadsheets export CSV; web apps and APIs want JSON. This script reads a CSV file whose first row holds the column names and writes a JSON list with one object per row. It only uses the standard library, so it runs anywhere Python 3 is installed.

Usage

python3 csv2json.py people.csv                     # print JSON to the terminal
python3 csv2json.py people.csv -o people.json      # write to a file
python3 csv2json.py export.csv -d ';' --types      # semicolon-separated, detect numbers
python3 csv2json.py --help

Given this input:

name,age,city,score
Ana,34,Lisbon,9.5
Ben,,Oslo,7

--types produces {"name": "Ana", "age": 34, "city": "Lisbon", "score": 9.5} and turns Ben’s empty age into null. Without --types, every value stays a string exactly as written in the file, which is the safe choice for things like postal codes or phone numbers with leading zeros.

The script

#!/usr/bin/env python3
"""Convert a CSV file to JSON (an array of objects, one per row)."""
import argparse
import csv
import json
import math
import sys
from pathlib import Path


def convert_value(text):
    if text == "":
        return None
    try:
        return int(text)
    except ValueError:
        pass
    try:
        number = float(text)
    except ValueError:
        return text
    return number if math.isfinite(number) else text


def read_rows(path, delimiter, infer_types):
    with path.open(newline="", encoding="utf-8-sig") as f:
        reader = csv.DictReader(f, delimiter=delimiter)
        for row in reader:
            if infer_types:
                yield {key: convert_value(value) for key, value in row.items()}
            else:
                yield row


def main():
    parser = argparse.ArgumentParser(description="Convert CSV to JSON.")
    parser.add_argument("csv_file", type=Path, help="input CSV file")
    parser.add_argument("-o", "--output", type=Path, help="output JSON file (default: print to stdout)")
    parser.add_argument("-d", "--delimiter", default=",", help="field separator (default: ,)")
    parser.add_argument("--types", action="store_true", help="turn numbers into numbers and empty cells into null")
    parser.add_argument("--indent", type=int, default=2, help="JSON indentation (default: 2)")
    args = parser.parse_args()

    if not args.csv_file.is_file():
        sys.exit(f"error: {args.csv_file} is not a file")

    rows = list(read_rows(args.csv_file, args.delimiter, args.types))
    text = json.dumps(rows, indent=args.indent, ensure_ascii=False)

    if args.output:
        args.output.write_text(text + "\n", encoding="utf-8")
        print(f"Wrote {len(rows)} rows to {args.output}", file=sys.stderr)
    else:
        print(text)


if __name__ == "__main__":
    main()

How it works

  • csv.DictReader uses the header row as keys and handles quoted fields that contain commas or line breaks. Never split CSV lines with line.split(","); quoting breaks it.
  • The file is opened with newline="", which the csv module requires, and encoding="utf-8-sig", which reads normal UTF-8 and also strips the invisible byte-order mark that Excel adds to UTF-8 exports.
  • convert_value tries int, then float, and keeps the original text otherwise. Values like nan or inf stay text, because JSON has no way to represent them.
  • ensure_ascii=False keeps accented characters readable in the output instead of \u escapes.
  • Messages go to standard error and data to standard output, so python3 csv2json.py data.csv > data.json produces a clean file.

Ideas to extend it

Read from standard input when the file name is -, add a --jsonl flag that writes one object per line for very large files, or flip the direction with csv.DictWriter to export JSON back to CSV.

See also

  • 0003 pathlib cheat sheet: files and folders in Python pathlib.Path is the modern way to build paths, read and write files, and list or search folders in Python. This page lists… Beginner · Reference · Any system Article Files & automation 15 Oct 2026
  • 0004 Logging instead of print The logging module gives every message a level, a timestamp and a destination you can change without editing code. It is the… Intermediate · Concept · Any system Article Files & automation 15 Oct 2026
  • 0010 Find duplicate files by content Scans folders and lists files with identical content, using file size first and SHA-256 hashes second. It is read-only and only reports… Intermediate · How-to · Any system Script Files & automation 15 Oct 2026
  • 0072 CSV vs JSON: choosing a format and avoiding the classic pitfalls CSV is a simple table of text; JSON holds nested, typed data. Both break in predictable ways: quoting, delimiters, encodings, numbers and… Beginner · Concept · Any system Article CSV & JSON 15 Oct 2026
  • 0073 Fix: json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0) Python's json module found nothing it could parse at the very first character. The input is usually empty, HTML, or already consumed.… Beginner · Fix · Any system Article Common errors · CSV & JSON 15 Oct 2026
  • 0074 pandas basics: read a CSV, filter rows and summarize with groupby Load a CSV into a pandas DataFrame, inspect it, filter rows with conditions, and compute totals per group, with the SQL equivalent… Intermediate · How-to · Any system Article Data analysis · Files & automation 15 Oct 2026

Repos in the wild

  • Requests: HTTP for humans psf/requests Requests is the classic Python library for calling web APIs and downloading pages, with a simple API for GET and POST requests, headers, JSON and sessions. GitHub
  • jq: command-line JSON processor jqlang/jq jq is a small command-line tool for reading, filtering and transforming JSON, like sed and awk for structured data. GitHub

History

Every saved edit is kept. The plot on the sleeve draws one line per edit. Open any edit to see exactly what changed.

  1. Commitpedia +4,001 chars

Report a problem

Something wrong, unsafe or copied? Tell the editors.
What is wrong?