Конвертация CSV в JSON на Python — json.dumps()

·Backend Developer·ПровереноPriya Sharma·Опубликовано

Используйте бесплатный CSV to JSON прямо в браузере — установка не требуется.

Попробовать CSV to JSON онлайн →

CSV-файлы встречаются повсюду — экспортированные отчёты, дампы баз данных, извлечённые журналы — и рано или поздно возникает необходимость конвертировать CSV в JSON на Python. Стандартная библиотека решает эту задачу двумя модулями: csv.DictReader превращает каждую строку в словарь Python, а json.dumps() сериализует эти словари в JSON-строку. Для быстрой разовой конвертации без кода воспользуйтесь конвертером CSV в JSON — он работает прямо в браузере. Это руководство охватывает весь программный путь: json.dump() против json.dumps(), запись JSON в файлы, сериализацию датаклассов, приведение типов для значений CSV, обработку datetime и Decimal, а также высокопроизводительные альтернативы вроде orjson. Все примеры рассчитаны на Python 3.10+.

  • csv.DictReader формирует список словарей — сериализуйте весь список через json.dump(rows, f, indent=2) для записи JSON-файла.
  • json.dump() пишет напрямую в файловый объект. json.dumps() возвращает строку. Выбор правильного метода избавляет от лишней копии данных.
  • Значения CSV всегда являются строками. Явно приводите числовые столбцы (int(), float()) перед сериализацией в JSON.
  • Передавайте ensure_ascii=False в json.dumps() для сохранения Unicode-символов — кириллицы, имён с диакритикой — в выводе.
  • Для datetime, UUID или Decimal из CSV используйте параметр default= с пользовательской функцией обратного вызова.
Before · json
After · json
order_id,product,quantity,price
ORD-7291,Wireless Keyboard,2,49.99
ORD-7292,USB-C Hub,1,34.50
[
  {
    "order_id": "ORD-7291",
    "product": "Wireless Keyboard",
    "quantity": "2",
    "price": "49.99"
  },
  {
    "order_id": "ORD-7292",
    "product": "USB-C Hub",
    "quantity": "1",
    "price": "34.50"
  }
]
Примечание:Обратите внимание: quantity и price отображаются как JSON-строки ("2", "49.99") в исходном выводе. В CSV нет системы типов — каждое значение является строкой. Исправление этого рассматривается в разделе о приведении типов ниже.

json.dumps() — Сериализация словаря Python в строку JSON

Модуль json входит в каждую установку Python — никакой pip install не требуется. json.dumps(obj) принимает объект Python (dict, list, строку, число, булево значение или None) и возвращает str с валидным JSON. Словарь Python выглядит похоже на JSON-объект, но это принципиально разные вещи: dict — это структура данных Python в памяти, а JSON-строка — сериализованный текст. Вызов json.dumps() устраняет это различие.

Минимальный пример — одна строка CSV в JSON

Python 3.10+
import json

# Одна строка CSV, представленная как словарь Python
server_entry = {
    "hostname": "web-prod-03",
    "ip_address": "10.0.12.47",
    "port": 8080,
    "region": "eu-west-1"
}

# Преобразование словаря в JSON-строку
json_string = json.dumps(server_entry)
print(json_string)
# {"hostname": "web-prod-03", "ip_address": "10.0.12.47", "port": 8080, "region": "eu-west-1"}
print(type(json_string))
# <class 'str'>

Результат — компактный однострочный JSON: удобен для передачи данных и хранения, но плохо читается. Добавьте indent=2 для читаемого вывода:

Python 3.10+ — вывод с отступами
import json

server_entry = {
    "hostname": "web-prod-03",
    "ip_address": "10.0.12.47",
    "port": 8080,
    "region": "eu-west-1"
}

pretty_json = json.dumps(server_entry, indent=2)
print(pretty_json)
# {
#   "hostname": "web-prod-03",
#   "ip_address": "10.0.12.47",
#   "port": 8080,
#   "region": "eu-west-1"
# }

Ещё два параметра, которые я использую почти всегда: sort_keys=True сортирует ключи словаря по алфавиту (удобно для сравнения JSON-файлов между версиями), а ensure_ascii=False сохраняет не-ASCII символы вместо их экранирования в последовательности \uXXXX.

Python 3.10+ — sort_keys и ensure_ascii
import json

warehouse_record = {
    "sku": "WH-9031",
    "location": "Склад Москва 3",
    "quantity": 240,
    "last_audit": "2026-03-10"
}

output = json.dumps(warehouse_record, indent=2, sort_keys=True, ensure_ascii=False)
print(output)
# {
#   "last_audit": "2026-03-10",
#   "location": "Склад Москва 3",
#   "quantity": 240,
#   "sku": "WH-9031"
# }

Замечание о параметре separators: по умолчанию это (", ", ": "), что добавляет пробелы после запятых и двоеточий. Для максимально компактного вывода (полезно при встраивании JSON в параметры URL или сжатии байт в API-ответах) передайте separators=(",", ":").

Примечание:Словарь Python и JSON-объект выглядят почти одинаково при выводе. Разница: json.dumps() преобразует Python True в JSON true, None в null, и оборачивает строки в двойные кавычки (Python допускает одинарные, JSON — нет). Всегда используйте json.dumps() для создания валидного JSON — не полагайтесь на str() или repr().

csv.DictReader в JSON-файл — Полный конвейер

Самая распространённая реальная задача — прочитать целый CSV-файл и сохранить его как JSON. Вот полный скрипт менее чем в 10 строк. csv.DictReader возвращает итератор объектов dict — по одному на строку, используя первую строку как ключи. Оборачивание в list() собирает все строки в список Python, который сериализуется в JSON-массив.

Python 3.10+ — полная конвертация CSV в JSON
import csv
import json

# Шаг 1: Читаем строки CSV в список словарей
with open("inventory.csv", "r", encoding="utf-8") as csv_file:
    rows = list(csv.DictReader(csv_file))

# Шаг 2: Записываем список как JSON-файл
with open("inventory.json", "w", encoding="utf-8") as json_file:
    json.dump(rows, json_file, indent=2, ensure_ascii=False)

print(f"Конвертировано {len(rows)} строк в inventory.json")

Два вызова open(): один для чтения CSV, другой для записи JSON. Вот и весь шаблон. Обратите внимание: здесь используется json.dump() (без s) — он пишет напрямую в файловый дескриптор. Использование json.dumps() вернуло бы строку, которую затем пришлось бы записывать отдельно через f.write(). json.dump() эффективнее по памяти, поскольку передаёт вывод потоком вместо построения всей строки в памяти.

Когда JSON нужен как строка, а не файл — для встраивания в API-пакет, вывода в stdout или вставки в столбец базы данных — переключитесь на json.dumps():

Python 3.10+ — строки CSV как JSON-строка
import csv
import json

with open("sensors.csv", "r", encoding="utf-8") as f:
    rows = list(csv.DictReader(f))

# Получаем JSON как строку вместо записи в файл
json_payload = json.dumps(rows, indent=2)
print(json_payload)
# [
#   {
#     "sensor_id": "TMP-4401",
#     "location": "Корпус 7 - Этаж 2",
#     "reading": "22.4",
#     "unit": "celsius"
#   },
#   ...
# ]

Одна строка против полного набора данных: если вызвать json.dumps(single_dict), получится JSON-объект ({...}). При вызове json.dumps(list_of_dicts) получится JSON-массив ([{...}, {...}]). Форма внешнего контейнера зависит от того, что передаётся. Большинство потребителей ожидают массив для табличных данных.

Обработка нестроковых значений — Приведение типов из CSV

Вот что подводит всех в первый раз: csv.DictReader возвращает каждое значение как строку. Число 42 в CSV становится строкой "42" в словаре. При прямой сериализации через json.dumps() в JSON появится "quantity": "42" вместо "quantity": 42. API с проверкой типов отклонят такой результат. Необходимо явно приводить значения.

Python 3.10+ — приведение типов для строк CSV
import csv
import json

def coerce_types(row: dict) -> dict:
    """Преобразование строковых значений в соответствующие типы Python."""
    return {
        "sensor_id": row["sensor_id"],
        "location": row["location"],
        "temperature": float(row["temperature"]),
        "humidity": float(row["humidity"]),
        "battery_pct": int(row["battery_pct"]),
        "active": row["active"].lower() == "true",
    }

with open("sensor_readings.csv", "r", encoding="utf-8") as f:
    rows = [coerce_types(row) for row in csv.DictReader(f)]

print(json.dumps(rows[0], indent=2))
# {
#   "sensor_id": "TMP-4401",
#   "location": "Корпус 7 - Этаж 2",
#   "temperature": 22.4,
#   "humidity": 58.3,
#   "battery_pct": 87,
#   "active": true
# }

Теперь temperature — вещественное число, battery_pct — целое, active — булево значение в JSON-выводе. Функция приведения типов специфична для вашей CSV-схемы — универсального способа угадать типы из CSV-данных нет, поэтому для каждого формата CSV пишется своя функция.

Сериализация пользовательских объектов и нестандартных типов

Модуль json Python не умеет сериализовать datetime, UUID, Decimalили пользовательские классы по умолчанию. Вызов json.dumps() для любого из них вызывает TypeError. Есть два подхода к решению.

Подход 1: Параметр default=

Передайте функцию в default=, которая преобразует неизвестные типы в нечто сериализуемое. Эта функция вызывается только для объектов, которые JSON-кодировщик не умеет обрабатывать.

Python 3.10+ — default= для datetime, UUID, Decimal
import json
from datetime import datetime
from decimal import Decimal
from uuid import UUID

def json_serial(obj):
    """Запасной сериализатор для нестандартных типов."""
    if isinstance(obj, datetime):
        return obj.isoformat()
    if isinstance(obj, UUID):
        return str(obj)
    if isinstance(obj, Decimal):
        return float(obj)
    raise TypeError(f"Type {type(obj).__name__} is not JSON serializable")

transaction = {
    "txn_id": UUID("a1b2c3d4-e5f6-7890-abcd-ef1234567890"),
    "amount": Decimal("149.99"),
    "currency": "EUR",
    "processed_at": datetime(2026, 3, 15, 14, 30, 0),
    "gateway": "stripe",
}

print(json.dumps(transaction, indent=2, default=json_serial))
# {
#   "txn_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
#   "amount": 149.99,
#   "currency": "EUR",
#   "processed_at": "2026-03-15T14:30:00",
#   "gateway": "stripe"
# }
Предупреждение:Всегда вызывайте TypeError в конце вашей функции default= для нераспознанных типов. Если возвращать None или молча пропускать их, в выводе появится null без каких-либо признаков потери данных.

Подход 2: Датаклассы с asdict()

Датаклассы Python дают строкам CSV правильное определение типов. Используйте dataclasses.asdict() для преобразования экземпляра датакласса в обычный словарь, а затем передайте его в json.dumps().

Python 3.10+ — сериализация датаклассов
import json
from dataclasses import dataclass, asdict
from datetime import datetime

@dataclass
class ShipmentRecord:
    tracking_id: str
    origin: str
    destination: str
    weight_kg: float
    shipped_at: datetime

def json_serial(obj):
    if isinstance(obj, datetime):
        return obj.isoformat()
    raise TypeError(f"Not serializable: {type(obj).__name__}")

shipment = ShipmentRecord(
    tracking_id="SHP-9827",
    origin="Москва",
    destination="Санкт-Петербург",
    weight_kg=1240.5,
    shipped_at=datetime(2026, 3, 12, 8, 0, 0),
)

print(json.dumps(asdict(shipment), indent=2, default=json_serial))
# {
#   "tracking_id": "SHP-9827",
#   "origin": "Москва",
#   "destination": "Санкт-Петербург",
#   "weight_kg": 1240.5,
#   "shipped_at": "2026-03-12T08:00:00"
# }
Примечание:asdict() рекурсивно преобразует вложенные датаклассы в словари. Если датакласс содержит список других датаклассов, всё дерево конвертируется — дополнительный код не нужен.

Справочник параметров json.dumps()

Полный список именованных аргументов, принимаемых json.dumps() и json.dump(). Обе функции принимают одинаковые параметры — json.dump() принимает дополнительный первый аргумент для файлового объекта.

Параметр
Тип
По умолчанию
Описание
obj
Any
(обязательный)
Объект Python для сериализации — dict, list, str, int, float, bool, None
indent
int | str | None
None
Число пробелов (или строка) на уровень отступа. None = компактный однострочный вывод
sort_keys
bool
False
Сортировать ключи словаря по алфавиту в выводе
ensure_ascii
bool
True
Экранировать все не-ASCII символы как \\uXXXX. Установите False для вывода UTF-8 напрямую
default
Callable | None
None
Функция для объектов, которые не сериализуются по умолчанию — возвращает сериализуемое значение или вызывает TypeError
separators
tuple[str, str] | None
None
Переопределить (разделитель_элементов, разделитель_ключей). Используйте (",", ":") для компактного вывода без пробелов
skipkeys
bool
False
Пропускать ключи dict, которые не являются str, int, float, bool или None, вместо вызова TypeError
allow_nan
bool
True
Разрешить float("nan"), float("inf"), float("-inf"). Установите False, чтобы вызывать ValueError для этих значений
cls
Type[JSONEncoder] | None
None
Пользовательский подкласс JSONEncoder вместо стандартного

csv.DictReader — Чтение CSV в словари Python

csv.DictReader — вторая половина конвейера CSV-в-JSON. Он оборачивает файловый объект и возвращает по одному dict на строку, используя первую строку как имена полей. По сравнению с csv.reader (который возвращает обычные списки), DictReader даёт именованный доступ к столбцам — без магических индексов вроде row[3].

Python 3.10+ — DictReader с пользовательским разделителем
import csv
import json

# Файл с разделителем-табуляцией из экспорта базы данных
with open("user_sessions.tsv", "r", encoding="utf-8") as f:
    reader = csv.DictReader(f, delimiter="\t")
    sessions = list(reader)

print(json.dumps(sessions[:2], indent=2))
# [
#   {
#     "session_id": "sess_8f2a91bc",
#     "user_id": "usr_4421",
#     "started_at": "2026-03-15T09:12:00Z",
#     "duration_sec": "342",
#     "pages_viewed": "7"
#   },
#   {
#     "session_id": "sess_3c7d44ef",
#     "user_id": "usr_1187",
#     "started_at": "2026-03-15T09:14:22Z",
#     "duration_sec": "128",
#     "pages_viewed": "3"
#   }
# ]
Предупреждение:csv.DictReader читает файл лениво — строки возвращаются по одной. Вызов list(reader) загружает все строки в память. Для файлов с миллионами строк обрабатывайте их потоком вместо полной загрузки.

Конвертация CSV из файла и API-ответа

Два производственных сценария: чтение CSV-файла с диска и его конвертация, а также получение CSV-данных из API-эндпоинта (многие сервисы отчётности возвращают CSV). Оба требуют правильной обработки ошибок.

Чтение CSV-файла → Конвертация → Запись JSON

Python 3.10+ — конвертация файла с обработкой ошибок
import csv
import json
import sys

def csv_to_json_file(csv_path: str, json_path: str) -> int:
    """Конвертировать CSV-файл в JSON. Возвращает количество записанных строк."""
    try:
        with open(csv_path, "r", encoding="utf-8") as f:
            rows = list(csv.DictReader(f))
    except FileNotFoundError:
        print(f"Error: {csv_path} not found", file=sys.stderr)
        sys.exit(1)
    except csv.Error as e:
        print(f"CSV parse error in {csv_path}: {e}", file=sys.stderr)
        sys.exit(1)

    with open(json_path, "w", encoding="utf-8") as f:
        json.dump(rows, f, indent=2, ensure_ascii=False)

    return len(rows)

count = csv_to_json_file("fleet_vehicles.csv", "fleet_vehicles.json")
print(f"Записано {count} записей в fleet_vehicles.json")

Получение CSV из API → Разбор → JSON

Python 3.10+ — CSV-ответ API в JSON
import csv
import io
import json
import urllib.request

def fetch_csv_as_json(url: str) -> str:
    """Получить CSV по URL и вернуть как JSON-строку."""
    try:
        with urllib.request.urlopen(url, timeout=10) as resp:
            raw = resp.read().decode("utf-8")
    except urllib.error.URLError as e:
        raise RuntimeError(f"Failed to fetch {url}: {e}")

    reader = csv.DictReader(io.StringIO(raw))
    rows = list(reader)

    if not rows:
        raise ValueError("CSV response was empty or had no data rows")

    return json.dumps(rows, indent=2, ensure_ascii=False)

# Пример: эндпоинт экспорта, возвращающий CSV
try:
    result = fetch_csv_as_json("https://reports.internal/api/v2/daily-metrics.csv")
    print(result)
except (RuntimeError, ValueError) as e:
    print(f"Error: {e}")

В обоих примерах явно указывается encoding="utf-8" при каждом открытии файла. Это важно для CSV-файлов с не-ASCII символами — имена с диакритикой, адреса со специальными символами, кириллический текст. Без явной кодировки Python использует системную по умолчанию, которая в Windows часто cp1252 и молча искажает многобайтовые символы.

Проверка JSON-вывода с помощью json.loads()

После конвертации CSV в JSON-строку можно проверить результат, разобрав его обратно через json.loads(). Это двойное преобразование выявляет проблемы с кодировкой, некорректные escape-последовательности или случайную конкатенацию строк, которая привела бы к невалидному JSON. Оборачивайте вызов в блок try/except.

Python 3.10+ — проверка двойным преобразованием
import json

json_string = json.dumps({"order_id": "ORD-7291", "total": 129.99})

# Проверяем валидность JSON, разбирая его обратно
try:
    parsed = json.loads(json_string)
    print(f"Валидный JSON с {len(parsed)} ключами")
except json.JSONDecodeError as e:
    print(f"Невалидный JSON: {e}")
# Валидный JSON с 2 ключами

Конвертация CSV в JSON из командной строки

Быстрые конвертации из терминала — файл скрипта не нужен. Флаг -c Python запускает встроенный код, а результат можно передать в python3 -m json.tool для форматирования с отступами.

bash — однострочная конвертация CSV в JSON
python3 -c "
import csv, json, sys
rows = list(csv.DictReader(sys.stdin))
json.dump(rows, sys.stdout, indent=2)
" < inventory.csv > inventory.json
bash — передача CSV и форматирование через json.tool
python3 -c "import csv,json,sys; print(json.dumps(list(csv.DictReader(sys.stdin))))" < data.csv | python3 -m json.tool
bash — конвертация и проверка через jq
python3 -c "import csv,json,sys; json.dump(list(csv.DictReader(sys.stdin)),sys.stdout)" < report.csv | jq .
Примечание:python3 -m json.tool — встроенный JSON-форматировщик. Он читает JSON из stdin, проверяет его и выводит с отступом в 4 пробела. Удобен для проверки того, что конвертация CSV в JSON дала валидный результат. Если нужен отступ в 2 пробела или фильтрация — используйте jq.

Высокопроизводительная альтернатива — orjson

Встроенный модуль json справляется с большинством CSV-файлов. Но если вы обрабатываете наборы данных с десятками тысяч строк в цикле, или ваш API должен сериализовать CSV-данные при каждом запросе, orjson работает в 5–10 раз быстрее. Написан на Rust, возвращает bytes вместо str, и нативно сериализует datetime, UUID и массивы numpy без пользовательской функции default=.

bash — установка orjson
pip install orjson
Python 3.10+ — CSV в JSON с orjson
import csv
import orjson

with open("telemetry_events.csv", "r", encoding="utf-8") as f:
    rows = list(csv.DictReader(f))

# orjson.dumps() возвращает bytes, а не str
json_bytes = orjson.dumps(rows, option=orjson.OPT_INDENT_2)

with open("telemetry_events.json", "wb") as f:  # примечание: "wb" для байтов
    f.write(json_bytes)

print(f"Записано {len(rows)} событий ({len(json_bytes)} байт)")

API несколько отличается: orjson.dumps() возвращает bytes и использует флаги option= вместо именованных аргументов. Открывайте файлы в режиме бинарной записи ("wb") при записи вывода orjson. Для получения строки вызовите .decode("utf-8") на результате.

Вывод в терминале с подсветкой синтаксиса — rich

Отладка конвертации CSV в JSON в терминале становится удобнее с цветным выводом. Библиотека rich отображает JSON с подсветкой синтаксиса — ключи, строки, числа и булевы значения получают разные цвета.

bash — установка rich
pip install rich
Python 3.10+ — вывод JSON через rich
import csv
import json
from rich.console import Console
from rich.syntax import Syntax

console = Console()

with open("deployment_log.csv", "r", encoding="utf-8") as f:
    rows = list(csv.DictReader(f))

json_output = json.dumps(rows[:3], indent=2, ensure_ascii=False)
syntax = Syntax(json_output, "json", theme="monokai", line_numbers=True)
console.print(syntax)
Предупреждение:rich добавляет ANSI-escape-коды в вывод. Не записывайте форматированный rich вывод в файл или API-ответ — он будет содержать невидимые управляющие символы. Используйте rich только для отображения в терминале.

Работа с большими CSV-файлами

Загрузка 500-мегабайтного CSV-файла через list(csv.DictReader(f)) выделяет весь набор данных в памяти, а json.dump() строит полную JSON-строку поверх этого. Для файлов крупнее 50–100 МБ переходите на потоковую обработку или записывайте NDJSON (JSON с разделителями-переносами строк) — по одному JSON-объекту на строку.

NDJSON — по одному JSON-объекту на строку

Python 3.10+ — потоковая конвертация CSV в NDJSON
import csv
import json

def csv_to_ndjson(csv_path: str, ndjson_path: str) -> int:
    """Конвертировать CSV в NDJSON, обрабатывая по одной строке."""
    count = 0
    with open(csv_path, "r", encoding="utf-8") as infile, \
         open(ndjson_path, "w", encoding="utf-8") as outfile:
        for row in csv.DictReader(infile):
            outfile.write(json.dumps(row, ensure_ascii=False) + "\n")
            count += 1
    return count

rows_written = csv_to_ndjson("access_log.csv", "access_log.ndjson")
print(f"Записано {rows_written} строк в access_log.ndjson")
# Каждая строка — самостоятельный JSON-объект:
# {"timestamp":"2026-03-15T09:12:00Z","method":"GET","path":"/api/v2/orders","status":"200"}
# {"timestamp":"2026-03-15T09:12:01Z","method":"POST","path":"/api/v2/payments","status":"201"}

Потоковая обработка с ijson для больших JSON-файлов

Python 3.10+ — ijson для чтения больших JSON
import ijson  # pip install ijson

def count_high_value_orders(json_path: str, threshold: float) -> int:
    """Подсчитать заказы выше порога без полной загрузки файла."""
    count = 0
    with open(json_path, "rb") as f:
        for item in ijson.items(f, "item"):
            if float(item.get("total", 0)) > threshold:
                count += 1
    return count

# Обработка 2-гигабайтного JSON-файла с постоянным объёмом памяти
high_value = count_high_value_orders("all_orders.json", 500.0)
print(f"Найдено {high_value} заказов на сумму свыше 500")
Примечание:Переходите на NDJSON или потоковую обработку, когда CSV превышает 50–100 МБ. ijson предназначен для чтения больших JSON-файлов обратно — для стороны записи шаблон NDJSON выше поддерживает постоянное использование памяти независимо от размера файла.

Распространённые ошибки

Использование json.dumps() с последующей отдельной записью в файл

Проблема: json.dumps() возвращает строку. Запись через f.write() работает, но создаёт ненужную промежуточную строку в памяти — расточительно для больших наборов данных.

Решение: Используйте json.dump(data, f) для прямой записи в файловый объект. Это передаёт вывод потоком без предварительного построения всей строки.

Before · Python
After · Python
json_string = json.dumps(rows, indent=2)
with open("output.json", "w") as f:
    f.write(json_string)  # ненужная промежуточная строка
with open("output.json", "w", encoding="utf-8") as f:
    json.dump(rows, f, indent=2, ensure_ascii=False)  # прямая запись
Забытое приведение строковых значений CSV к числам

Проблема: csv.DictReader возвращает все значения как строки. В JSON-выводе появляется "quantity": "5" вместо "quantity": 5, что ломает строго типизированных потребителей API.

Решение: Явно приводите числовые столбцы с помощью int() или float() перед сериализацией.

Before · Python
After · Python
rows = list(csv.DictReader(f))
json.dumps(rows)
# [{"port": "8080", "workers": "4"}]  ← строки, не числа
rows = list(csv.DictReader(f))
for row in rows:
    row["port"] = int(row["port"])
    row["workers"] = int(row["workers"])
json.dumps(rows)
# [{"port": 8080, "workers": 4}]  ← правильные целые числа
Пропущенный encoding='utf-8' при открытии файла

Проблема: В Windows кодировка по умолчанию — cp1252. Не-ASCII символы (имена с диакритикой, кириллица) молча искажаются или вызывают UnicodeDecodeError.

Решение: Всегда передавайте encoding='utf-8' в open() как при чтении CSV, так и при записи JSON.

Before · Python
After · Python
with open("locations.csv", "r") as f:  # использует системную кодировку по умолчанию
    rows = list(csv.DictReader(f))
with open("locations.csv", "r", encoding="utf-8") as f:
    rows = list(csv.DictReader(f))
Использование str() или repr() вместо json.dumps()

Проблема: str(my_dict) производит синтаксис Python (одинарные кавычки, True, None), который не является валидным JSON. API и JSON-парсеры его отклоняют.

Решение: Всегда используйте json.dumps() для создания валидного JSON. Он преобразует True в true, None в null и использует двойные кавычки.

Before · Python
After · Python
output = str({"active": True, "note": None})
# "{'active': True, 'note': None}"  ← НЕ валидный JSON
output = json.dumps({"active": True, "note": None})
# '{"active": true, "note": null}'  ← валидный JSON

json.dumps() и альтернативы — Быстрое сравнение

Метод
Вывод
Валидный JSON
Пользовательские типы
Скорость
Требует установки
json.dumps()
str
через параметр default=
Базовый
Нет (stdlib)
json.dump()
запись в файл
через параметр default=
Базовый
Нет (stdlib)
csv.DictReader + json
str или файл
через параметр default=
Базовый
Нет (stdlib)
pandas to_json()
str или файл
✓ нативный datetime
~в 2 раза быстрее для больших данных
pip install pandas
orjson.dumps()
bytes
✓ нативный datetime/UUID
в 5–10 раз быстрее
pip install orjson
dataclasses.asdict() + json
str
через параметр default=
Базовый
Нет (stdlib)
polars write_json()
str или файл
✓ нативный datetime
~в 3 раза быстрее для больших данных
pip install polars

Для большинства конвертаций CSV в JSON стандартная библиотека csv + json — правильный выбор: ноль зависимостей, поставляется с Python, работает везде. Обращайтесь к orjson, когда профилирование показывает, что сериализация является узким местом — разница в скорости реальна при больших масштабах. Используйте pandas, когда также нужна очистка данных, фильтрация или агрегация перед конвертацией в JSON. Если нужна быстрая конвертация без написания кода, онлайн-конвертер CSV в JSON справляется с этим мгновенно.

Часто задаваемые вопросы

В чём разница между json.dump() и json.dumps() в Python?

json.dump(obj, file) записывает JSON-вывод напрямую в файлоподобный объект (любой объект с методом .write()). json.dumps(obj) возвращает строку в формате JSON. Используйте json.dump() при записи в файл, json.dumps() — когда JSON нужен как строка Python для журналирования, встраивания в пакет данных или отправки через сокет. Оба метода принимают одинаковые именованные аргументы (indent, sort_keys, ensure_ascii, default).

Как преобразовать словарь Python в строку JSON?

Вызовите json.dumps(your_dict). Возвращаемое значение — str с валидным JSON. Добавьте indent=2 для читаемого вывода. Если словарь содержит не-ASCII значения, передайте ensure_ascii=False для сохранения символов вроде букв с диакритикой или текста на кириллице.

Python 3.10+
import json

server_config = {"host": "api.internal", "port": 8443, "debug": False}
json_string = json.dumps(server_config, indent=2)
print(json_string)
# {
#   "host": "api.internal",
#   "port": 8443,
#   "debug": false
# }

Как сохранить список словарей Python в JSON-файл?

Откройте файл в режиме записи с кодировкой UTF-8, затем вызовите json.dump(your_list, f, indent=2, ensure_ascii=False). Всегда используйте json.dump() (не json.dumps()) для записи в файл — он пишет напрямую в файловый дескриптор без создания промежуточной строки в памяти.

Python 3.10+
import json

records = [
    {"order_id": "ORD-4821", "total": 129.99, "currency": "USD"},
    {"order_id": "ORD-4822", "total": 89.50, "currency": "EUR"},
]

with open("orders.json", "w", encoding="utf-8") as f:
    json.dump(records, f, indent=2, ensure_ascii=False)

Почему json.dumps() преобразует True в true, а None в null?

Булевы значения Python (True, False) и None не являются допустимыми токенами JSON. Спецификация JSON использует строчные true, false и null. json.dumps() выполняет это преобразование автоматически — True становится true, False становится false, None становится null. Конвертировать их вручную не нужно. В обратную сторону json.loads() отображает их обратно в типы Python.

Как обрабатывать объекты datetime при конвертации CSV-данных в JSON?

Передайте функцию default= в json.dumps(), которая преобразует объекты datetime в строки ISO 8601. Функция default вызывается для любого объекта, который json не умеет сериализовать нативно. Возвращайте obj.isoformat() для экземпляров datetime и вызывайте TypeError для всего остального.

Python 3.10+
import json
from datetime import datetime

def json_default(obj):
    if isinstance(obj, datetime):
        return obj.isoformat()
    raise TypeError(f"Not serializable: {type(obj)}")

event = {"action": "login", "timestamp": datetime(2026, 3, 15, 9, 30, 0)}
print(json.dumps(event, default=json_default))
# {"action": "login", "timestamp": "2026-03-15T09:30:00"}

Можно ли конвертировать CSV в JSON без pandas?

Да. Стандартной библиотеки Python достаточно. Используйте csv.DictReader для чтения каждой строки как словаря, соберите строки в список и сериализуйте с помощью json.dump() или json.dumps(). Сторонние библиотеки не нужны. pandas стоит добавлять только если вам также нужна очистка данных, вывод типов, или вы уже используете его в проекте.

Python 3.10+
import csv
import json

with open("inventory.csv", "r", encoding="utf-8") as csv_file:
    rows = list(csv.DictReader(csv_file))

with open("inventory.json", "w", encoding="utf-8") as json_file:
    json.dump(rows, json_file, indent=2, ensure_ascii=False)

Для однокнопочной альтернативы без написания кода на Python воспользуйтесь конвертером CSV в JSON — вставьте данные и получите форматированный JSON-вывод немедленно.

Связанные инструменты

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 SharmaТехнический рецензент

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.