How to convert CSV to JSON in Python

csv.DictReader plus json.dump converts CSV to JSON in two lines, but every value comes out as a string. This script also types numbers and booleans, handles Excel's BOM and semicolons, and can rebuild nested objects.

1. The two-line version

import csv, json
json.dump(list(csv.DictReader(open('data.csv', newline='', encoding='utf-8-sig'))), open('data.json', 'w'), indent=2)

Each row becomes an object keyed by the header row, but "42" stays a string and empty cells become "". Use utf-8-sig, not utf-8: files saved by Excel start with a BOM, which would otherwise end up in the first key ("\ufeffid").

2. The full script

Save as csv2json.py:

import csv, json, re, sys

NUM = re.compile(r'-?(0|[1-9]\d*)(\.\d+)?([eE][-+]?\d+)?')

def typed(v):
    # '42' -> 42, '3.5' -> 3.5, 'TRUE' -> True, '' -> None; ids with leading zeros ('02134') stay text
    if v == '': return None
    if NUM.fullmatch(v): return float(v) if any(c in v for c in '.eE') else int(v)
    if v.lower() in ('true', 'false'): return v.lower() == 'true'
    return v

def nest(row):
    # {'address.city': 'X'} -> {'address': {'city': 'X'}}
    out = {}
    for key, value in row.items():
        *path, last = key.split('.')
        node = out
        for part in path: node = node.setdefault(part, {})
        node[last] = value
    return out

with open(sys.argv[1], newline='', encoding='utf-8-sig') as f:
    dialect = csv.Sniffer().sniff(f.read(4096), delimiters=',;\t|'); f.seek(0)
    rows = [nest({k: typed(v) for k, v in r.items()}) for r in csv.DictReader(f, dialect=dialect)]
with open(sys.argv[2], 'w', encoding='utf-8') as f:
    json.dump(rows, f, indent=2, ensure_ascii=False)
print(f'{len(rows)} rows -> {sys.argv[2]}')

3. Run it

curl -sL https://raw.githubusercontent.com/datasets/country-codes/main/data/country-codes.csv -o countries.csv
python3 csv2json.py countries.csv countries.json

Our run printed 249 rows -> countries.json. The start of the first object:

{"FIFA": "AFG", "Dial": 93, "ISO3166-1-Alpha-3": "AFG", "MARC": "af", "is_independent": "Yes", "ISO3166-1-numeric": 4, "GAUL": 1, ...
 "Intermediate Region Code": null, ...}

4. What it handles

5. Limits

6. No code

Paste the cells from Excel, Google Sheets or a CSV file into the free Excel / CSV to JSON converter: same typing rules, optional nesting with arrays, and nothing is uploaded.

Frequently asked questions

How do I convert CSV to JSON in Python without pandas?

Use csv.DictReader to read rows as dictionaries and json.dump to write them, as in the two-line version above. The full script adds typing, separator detection and nesting.

Why are all my numbers strings?

The csv module never converts values; every cell is text. Convert them yourself, as the typed() function above does, or with pandas (pd.read_csv(...).to_json(orient='records')).

Why does my first key start with a strange character?

The file has a UTF-8 BOM (Excel adds one). Open it with encoding='utf-8-sig'.

Written with AI assistance. The script was run on 2026-10-01 with Python 3 standard library only, on the open country-codes dataset (datasets/country-codes on GitHub: 249 rows, 56 columns), on a semicolon-separated file with a BOM, accents and empty cells, and on the CSV produced by our JSON to CSV guide (nested JSON restored). PlainTables is our extension; the other methods are free and built into Excel, Google Sheets and pandas.