Convertir CSV a JSON en Python — Guía json.dumps()

·Backend Developer·Revisado porPriya Sharma·Publicado

Usa el CSV to JSON gratuito directamente en tu navegador — sin instalación.

Probar CSV to JSON online →

Los archivos CSV aparecen en todas partes — informes exportados, volcados de bases de datos, extractos de registros — y tarde o temprano necesitas convertir ese CSV a JSON en Python. La biblioteca estándar gestiona esto con dos módulos: csv.DictReader convierte cada fila en un dict Python, y json.dumps() serializa esos dicts a una cadena JSON. Para una conversión rápida sin código, el conversor CSV a JSON lo hace al instante en el navegador. Esta guía cubre el proceso completo por código: json.dump() vs json.dumps(), escritura de JSON en archivos, serialización de dataclasses, conversión de tipos para valores CSV, gestión de datetime y Decimal, y alternativas de alto rendimiento como orjson. Todos los ejemplos tienen como objetivo Python 3.10+.

  • csv.DictReader produce una lista de dicts — serializa la lista completa con json.dump(rows, f, indent=2) para escribir un archivo JSON.
  • json.dump() escribe directamente en un objeto de archivo. json.dumps() devuelve una cadena. Elige el correcto y evitas una copia innecesaria.
  • Los valores CSV son siempre cadenas. Convierte las columnas numéricas explícitamente (int(), float()) antes de serializar a JSON.
  • Pasa ensure_ascii=False a json.dumps() para preservar caracteres Unicode — nombres acentuados, texto CJK — en la salida.
  • Para datetime, UUID o Decimal provenientes de CSV, usa el parámetro default= con una función de respaldo personalizada.
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"
  }
]
Nota:Observa que quantity y price aparecen como cadenas JSON ("2", "49.99") en la salida sin procesar. CSV no tiene sistema de tipos — cada valor es una cadena. Cómo solucionar esto se cubre en la sección de conversión de tipos más abajo.

json.dumps() — Serializar un Dict Python a una Cadena JSON

El módulo json viene incluido en toda instalación Python — no se requiere pip install. json.dumps(obj) toma un objeto Python (dict, list, string, número, bool o None) y devuelve un str que contiene JSON válido. Un diccionario Python se parece a un objeto JSON, pero son fundamentalmente diferentes: un dict es una estructura de datos Python en memoria, y una cadena JSON es texto serializado. Llamar a json.dumps() cierra esa brecha.

Ejemplo mínimo — Una fila CSV a JSON

Python 3.10+
import json

# Una sola fila CSV representada como dict Python
server_entry = {
    "hostname": "web-prod-03",
    "ip_address": "10.0.12.47",
    "port": 8080,
    "region": "eu-west-1"
}

# Convertir dict a cadena 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'>

Eso produce JSON compacto en una sola línea — bueno para payloads y almacenamiento, difícil de leer. Añade indent=2 para obtener una salida legible por humanos:

Python 3.10+ — salida con formato legible
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"
# }

Dos parámetros más que uso en casi cada llamada: sort_keys=True ordena las claves del diccionario alfabéticamente (muy útil para comparar archivos JSON entre versiones), y ensure_ascii=False preserva los caracteres no ASCII en lugar de escaparlos a secuencias \uXXXX.

Python 3.10+ — sort_keys y ensure_ascii
import json

warehouse_record = {
    "sku": "WH-9031",
    "location": "Valencia Almacén 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": "Valencia Almacén 3",
#   "quantity": 240,
#   "sku": "WH-9031"
# }

Una nota sobre el parámetro separators: el valor por defecto es (", ", ": "), que añade espacios tras las comas y los dos puntos. Para la salida más compacta posible (útil al incrustar JSON en parámetros de URL o al reducir bytes en respuestas de API), pasa separators=(",", ":").

Nota:Un dict Python y un objeto JSON lucen casi idénticos al imprimirlos. La diferencia: json.dumps() convierte el Python True al JSON true, None a null, y envuelve las cadenas en comillas dobles (Python permite comillas simples, JSON no). Usa siempre json.dumps() para producir JSON válido — no confíes en str() ni en repr().

csv.DictReader a archivo JSON — El Pipeline Completo

La tarea más habitual en producción es leer un archivo CSV completo y guardarlo como JSON. Aquí está el script de extremo a extremo en menos de 10 líneas. csv.DictReader produce un iterador de objetos dict — uno por fila, usando la primera línea como claves. Envolverlo en list() recoge todas las filas en una lista Python, que se serializa como un array JSON.

Python 3.10+ — conversión completa de CSV a JSON
import csv
import json

# Paso 1: Leer filas CSV en una lista de dicts
with open("inventory.csv", "r", encoding="utf-8") as csv_file:
    rows = list(csv.DictReader(csv_file))

# Paso 2: Escribir la lista como archivo JSON
with open("inventory.json", "w", encoding="utf-8") as json_file:
    json.dump(rows, json_file, indent=2, ensure_ascii=False)

print(f"Convertidas {len(rows)} filas a inventory.json")

Dos llamadas a open(): una para leer el CSV, otra para escribir el JSON. Ese es todo el patrón. Fíjate que se usa json.dump() (sin la s) — escribe directamente en el manejador de archivo. Usar json.dumps() devolvería una cadena que después tendrías que escribir por separado con f.write(). json.dump() es más eficiente en memoria porque transmite la salida en lugar de construir la cadena completa en memoria primero.

Cuando necesitas el JSON como cadena en lugar de como archivo — para incrustarlo en un payload de API, imprimirlo en stdout o insertarlo en una columna de base de datos — cambia a json.dumps():

Python 3.10+ — filas CSV como cadena JSON
import csv
import json

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

# Obtener el JSON como cadena en lugar de escribirlo en un archivo
json_payload = json.dumps(rows, indent=2)
print(json_payload)
# [
#   {
#     "sensor_id": "TMP-4401",
#     "location": "Edificio 7 - Piso 2",
#     "reading": "22.4",
#     "unit": "celsius"
#   },
#   ...
# ]

Fila única vs. conjunto completo: si llamas a json.dumps(single_dict) obtienes un objeto JSON ({...}). Llama a json.dumps(list_of_dicts) y obtienes un array JSON ([{...}, {...}]). La forma del contenedor exterior depende de lo que pases. La mayoría de los consumidores esperan un array para datos tabulares.

Gestión de Valores No Cadena — Conversión de Tipos desde CSV

Aquí está lo que le pilla a todo el mundo la primera vez: csv.DictReader devuelve cada valor como cadena. El número 42 en tu CSV se convierte en la cadena "42" en el dict. Si lo serializas directamente con json.dumps(), tu JSON tendrá "quantity": "42" en lugar de "quantity": 42. Las APIs que validan tipos rechazarán esto. Necesitas hacer la conversión de tipos de forma explícita.

Python 3.10+ — conversión de tipos para filas CSV
import csv
import json

def coerce_types(row: dict) -> dict:
    """Convierte valores de cadena a los tipos Python apropiados."""
    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": "Edificio 7 - Piso 2",
#   "temperature": 22.4,
#   "humidity": 58.3,
#   "battery_pct": 87,
#   "active": true
# }

Ahora temperature es un float, battery_pct es un entero y active es un booleano en la salida JSON. La función de conversión es específica del esquema de tu CSV — no hay una forma genérica de inferir tipos a partir de datos CSV, así que escribo una función por cada formato CSV.

Serialización de Objetos Personalizados y Tipos No Estándar

El módulo json de Python no puede serializar datetime, UUID, Decimal ni clases personalizadas de forma nativa. Llamar a json.dumps() con cualquiera de estos lanza un TypeError. Hay dos enfoques para gestionar esto.

Enfoque 1: El parámetro default=

Pasa una función a default= que convierta los tipos desconocidos a algo serializable. Esta función solo se llama para los objetos que el codificador JSON no sabe gestionar.

Python 3.10+ — default= para datetime, UUID, Decimal
import json
from datetime import datetime
from decimal import Decimal
from uuid import UUID

def json_serial(obj):
    """Serializador de respaldo para tipos no estándar."""
    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"
# }
Advertencia:Lanza siempre TypeError al final de tu función default= para los tipos no reconocidos. Si devuelves None o los omites en silencio, obtienes null en la salida sin ninguna indicación de que se han perdido datos.

Enfoque 2: Dataclasses con asdict()

Los dataclasses de Python dan a tus filas CSV una definición de tipo adecuada. Usa dataclasses.asdict() para convertir una instancia de dataclass a un dict plano y después pásalo a json.dumps().

Python 3.10+ — serialización de dataclass
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="Buenos Aires",
    destination="Madrid",
    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": "Buenos Aires",
#   "destination": "Madrid",
#   "weight_kg": 1240.5,
#   "shipped_at": "2026-03-12T08:00:00"
# }
Nota:asdict() convierte recursivamente los dataclasses anidados en dicts. Si tu dataclass contiene una lista de otros dataclasses, todo el árbol se convierte — no se necesita código adicional.

Referencia de Parámetros de json.dumps()

Lista completa de los argumentos de palabra clave aceptados por json.dumps() y json.dump(). Ambas funciones aceptan parámetros idénticos — json.dump() recibe un argumento adicional inicial para el objeto de archivo.

Parámetro
Tipo
Valor por defecto
Descripción
obj
Any
(requerido)
El objeto Python a serializar — dict, list, str, int, float, bool, None
indent
int | str | None
None
Número de espacios (o una cadena) por nivel de indentación. None = salida compacta en una sola línea
sort_keys
bool
False
Ordena las claves del diccionario alfabéticamente en la salida
ensure_ascii
bool
True
Escapa todos los caracteres no ASCII como \\uXXXX. Establecer False para emitir UTF-8 directamente
default
Callable | None
None
Función llamada para objetos no serializables por defecto — devuelve un valor serializable o lanza TypeError
separators
tuple[str, str] | None
None
Reemplaza (separador_de_elementos, separador_de_clave). Usa (",", ":") para salida compacta sin espacios
skipkeys
bool
False
Omite las claves del dict que no sean str, int, float, bool o None en lugar de lanzar TypeError
allow_nan
bool
True
Permite float("nan"), float("inf"), float("-inf"). Establecer False para lanzar ValueError con estos valores
cls
Type[JSONEncoder] | None
None
Subclase personalizada de JSONEncoder a usar en lugar del codificador por defecto

csv.DictReader — Lectura de CSV en Dicts Python

csv.DictReader es la otra mitad del pipeline CSV a JSON. Envuelve un objeto de archivo y produce un dict por fila, usando la primera línea como nombres de campo. En comparación con csv.reader (que produce listas simples), DictReader da acceso a las columnas por nombre — sin índices mágicos como row[3].

Python 3.10+ — DictReader con delimitador personalizado
import csv
import json

# Archivo separado por tabulaciones desde una exportación de base de datos
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"
#   }
# ]
Advertencia:csv.DictReader lee el archivo de forma perezosa — produce filas de una en una. Llamar a list(reader) carga todas las filas en memoria. Para archivos con millones de filas, procesa las filas de forma continua en lugar de recopilarlas todas.

Convertir CSV desde un Archivo y una Respuesta de API

Dos escenarios de producción: leer un archivo CSV del disco y convertirlo, y obtener datos CSV desde un endpoint de API (muchos servicios de informes devuelven CSV). Ambos necesitan un manejo adecuado de errores.

Leer archivo CSV → Convertir → Escribir JSON

Python 3.10+ — conversión de archivo con manejo de errores
import csv
import json
import sys

def csv_to_json_file(csv_path: str, json_path: str) -> int:
    """Convierte un archivo CSV a JSON. Devuelve el número de filas escritas."""
    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"Wrote {count} records to fleet_vehicles.json")

Obtener CSV desde API → Parsear → JSON

Python 3.10+ — respuesta CSV de API a JSON
import csv
import io
import json
import urllib.request

def fetch_csv_as_json(url: str) -> str:
    """Obtiene CSV desde una URL y lo devuelve como cadena 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)

# Ejemplo: endpoint de exportación que devuelve 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}")

Ambos ejemplos usan encoding="utf-8" explícito en cada apertura de archivo. Esto importa para archivos CSV con caracteres no ASCII — nombres acentuados, direcciones con caracteres especiales, texto CJK. Sin codificación explícita, Python recurre al valor predeterminado del sistema, que en Windows suele ser cp1252 y corromperá silenciosamente los caracteres multibyte.

Verificar la Salida JSON con json.loads()

Después de convertir CSV a una cadena JSON, puedes verificar el resultado parseándolo de vuelta con json.loads(). Esta verificación de ida y vuelta detecta problemas de codificación, secuencias de escape rotas o concatenaciones accidentales de cadenas que producirían JSON inválido. Envuelve la llamada en un bloque try/except.

Python 3.10+ — validación de ida y vuelta
import json

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

# Verificar que es JSON válido parseándolo de vuelta
try:
    parsed = json.loads(json_string)
    print(f"Valid JSON with {len(parsed)} keys")
except json.JSONDecodeError as e:
    print(f"Invalid JSON: {e}")
# Valid JSON with 2 keys

Conversión de CSV a JSON desde la Línea de Comandos

Conversiones rápidas desde la terminal — sin necesidad de un archivo de script. El flag -c de Python ejecuta código en línea, y puedes redirigir el resultado a través de python3 -m json.tool para formatear la salida.

bash — one-liner CSV a 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 — redirigir archivo CSV y formatear con json.tool
python3 -c "import csv,json,sys; print(json.dumps(list(csv.DictReader(sys.stdin))))" < data.csv | python3 -m json.tool
bash — convertir y validar con jq
python3 -c "import csv,json,sys; json.dump(list(csv.DictReader(sys.stdin)),sys.stdout)" < report.csv | jq .
Nota:python3 -m json.tool es el formateador JSON integrado. Lee JSON desde stdin, lo valida y lo imprime con indentación de 4 espacios. Es útil para verificar que tu conversión de CSV a JSON produjo una salida válida. Si prefieres una indentación de 2 espacios o necesitas filtrado, usa jq en su lugar.

Alternativa de Alto Rendimiento — orjson

El módulo json integrado funciona bien para la mayoría de archivos CSV. Pero si procesas conjuntos de datos con decenas de miles de filas en un bucle, o tu API necesita serializar datos derivados de CSV en cada petición, orjson es 5–10 veces más rápido. Está escrito en Rust, devuelve bytes en lugar de str, y serializa de forma nativa datetime, UUID y arrays numpy sin necesidad de una función default= personalizada.

bash — instalar orjson
pip install orjson
Python 3.10+ — CSV a JSON con orjson
import csv
import orjson

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

# orjson.dumps() devuelve bytes, no str
json_bytes = orjson.dumps(rows, option=orjson.OPT_INDENT_2)

with open("telemetry_events.json", "wb") as f:  # nota: "wb" para bytes
    f.write(json_bytes)

print(f"Wrote {len(rows)} events ({len(json_bytes)} bytes)")

La API es ligeramente diferente: orjson.dumps() devuelve bytes y usa flags option= en lugar de argumentos de palabra clave. Abre los archivos en modo escritura binaria ("wb") al escribir salida de orjson. Si necesitas una cadena, llama a .decode("utf-8") en el resultado.

Salida con Resaltado de Sintaxis en Terminal — rich

Depurar conversiones de CSV a JSON en la terminal es más fácil con salida coloreada. La biblioteca rich renderiza JSON con resaltado de sintaxis — claves, cadenas, números y booleanos tienen cada uno su propio color.

bash — instalar rich
pip install rich
Python 3.10+ — salida JSON con 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)
Advertencia:rich añade códigos de escape ANSI a la salida. No escribas salida formateada con rich en un archivo ni en una respuesta de API — contendrá caracteres de control invisibles. Usa rich únicamente para la visualización en terminal.

Trabajo con Archivos CSV Grandes

Cargar un archivo CSV de 500 MB con list(csv.DictReader(f)) asigna todo el conjunto de datos en memoria, y después json.dump() construye la cadena JSON completa encima de eso. Para archivos de más de 50–100 MB, cambia a un enfoque de streaming o escribe NDJSON (JSON delimitado por nueva línea) — un objeto JSON por línea.

NDJSON — Un Objeto JSON por Línea

Python 3.10+ — CSV a NDJSON en streaming
import csv
import json

def csv_to_ndjson(csv_path: str, ndjson_path: str) -> int:
    """Convierte CSV a NDJSON procesando una fila a la vez."""
    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"Wrote {rows_written} lines to access_log.ndjson")
# Cada línea es un objeto JSON independiente:
# {"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"}

Streaming con ijson para Entradas JSON Grandes

Python 3.10+ — ijson para leer JSON grande
import ijson  # pip install ijson

def count_high_value_orders(json_path: str, threshold: float) -> int:
    """Cuenta pedidos por encima de un umbral sin cargar el archivo completo."""
    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

# Procesar un archivo JSON de 2 GB con uso de memoria constante
high_value = count_high_value_orders("all_orders.json", 500.0)
print(f"Found {high_value} orders above $500")
Nota:Cambia a NDJSON o streaming cuando el CSV supere los 50–100 MB. ijson es para leer archivos JSON grandes de vuelta — para el lado de escritura, el patrón NDJSON anterior mantiene el uso de memoria constante independientemente del tamaño del archivo.

Errores Comunes

Usar json.dumps() y después escribir en un archivo por separado

Problema: json.dumps() devuelve una cadena. Escribirla con f.write() funciona, pero crea una cadena intermedia innecesaria en memoria — un desperdicio para conjuntos de datos grandes.

Solución: Usa json.dump(data, f) para escribir directamente en el objeto de archivo. Transmite la salida sin construir la cadena completa primero.

Before · Python
After · Python
json_string = json.dumps(rows, indent=2)
with open("output.json", "w") as f:
    f.write(json_string)  # unnecessary intermediate string
with open("output.json", "w", encoding="utf-8") as f:
    json.dump(rows, f, indent=2, ensure_ascii=False)  # direct write
Olvidar convertir los valores de cadena CSV a números

Problema: csv.DictReader devuelve todos los valores como cadenas. La salida JSON contiene "quantity": "5" en lugar de "quantity": 5, lo que rompe los consumidores de API que validan tipos.

Solución: Convierte las columnas numéricas explícitamente con int() o float() antes de serializar.

Before · Python
After · Python
rows = list(csv.DictReader(f))
json.dumps(rows)
# [{"port": "8080", "workers": "4"}]  ← cadenas, no números
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}]  ← enteros correctos
Omitir encoding='utf-8' al abrir archivos

Problema: En Windows, la codificación por defecto es cp1252. Los caracteres no ASCII (nombres acentuados, texto CJK) se corrompen silenciosamente o lanzan UnicodeDecodeError.

Solución: Pasa siempre encoding='utf-8' a open() tanto para la lectura del CSV como para la escritura del JSON.

Before · Python
After · Python
with open("locations.csv", "r") as f:  # usa la codificación predeterminada del sistema
    rows = list(csv.DictReader(f))
with open("locations.csv", "r", encoding="utf-8") as f:
    rows = list(csv.DictReader(f))
Usar str() o repr() en lugar de json.dumps()

Problema: str(my_dict) produce sintaxis Python (comillas simples, True, None) que no es JSON válido. Las APIs y los parsers JSON lo rechazan.

Solución: Usa siempre json.dumps() para producir JSON válido. Convierte True en true, None en null y usa comillas dobles.

Before · Python
After · Python
output = str({"active": True, "note": None})
# "{'active': True, 'note': None}"  ← NO es JSON válido
output = json.dumps({"active": True, "note": None})
# '{"active": true, "note": null}'  ← JSON válido

json.dumps() vs Alternativas — Comparación Rápida

Método
Salida
JSON válido
Tipos personalizados
Velocidad
Requiere instalación
json.dumps()
str
mediante el parámetro default=
Referencia
No (stdlib)
json.dump()
escribe en archivo
mediante el parámetro default=
Referencia
No (stdlib)
csv.DictReader + json
str o archivo
mediante el parámetro default=
Referencia
No (stdlib)
pandas to_json()
str o archivo
✓ datetime nativo
~2x más rápido para datos grandes
pip install pandas
orjson.dumps()
bytes
✓ datetime/UUID nativo
5–10x más rápido
pip install orjson
dataclasses.asdict() + json
str
mediante el parámetro default=
Referencia
No (stdlib)
polars write_json()
str o archivo
✓ datetime nativo
~3x más rápido para datos grandes
pip install polars

Para la mayoría de las conversiones de CSV a JSON, la combinación de la biblioteca estándar csv + json es la elección correcta: cero dependencias, incluida con Python, funciona en cualquier lugar. Recurre a orjson cuando el profiling muestre que la serialización es un cuello de botella — la diferencia de velocidad es real a escala. Usa pandas cuando también necesites limpieza de datos, filtrado o agregación antes de convertir a JSON. Si solo necesitas una conversión rápida sin escribir código, el conversor online de CSV a JSON lo hace al instante.

Preguntas Frecuentes

¿Cuál es la diferencia entre json.dump() y json.dumps() en Python?

json.dump(obj, file) escribe la salida JSON directamente en un objeto de tipo archivo (cualquier objeto con un método .write()). json.dumps(obj) devuelve una cadena con formato JSON. Usa json.dump() al escribir en un archivo, json.dumps() cuando necesitas el JSON como cadena Python para registros, incrustarlo en un payload o enviarlo a través de un socket. Ambas funciones aceptan los mismos argumentos de palabra clave (indent, sort_keys, ensure_ascii, default).

¿Cómo convierto un diccionario Python a una cadena JSON?

Llama a json.dumps(tu_dict). El valor de retorno es un str que contiene JSON válido. Añade indent=2 para obtener una salida legible. Si tu diccionario contiene valores no ASCII, pasa ensure_ascii=False para preservar caracteres como letras acentuadas o texto CJK.

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
# }

¿Cómo guardo una lista de dicts Python como archivo JSON?

Abre un archivo en modo escritura con codificación UTF-8 y llama a json.dump(tu_lista, f, indent=2, ensure_ascii=False). Usa siempre json.dump() (no json.dumps()) para la salida a archivo — escribe directamente en el manejador de archivo sin crear una cadena intermedia en memoria.

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)

¿Por qué json.dumps() convierte True en true y None en null?

Los booleanos de Python (True, False) y None no son tokens JSON válidos. La especificación JSON usa las minúsculas true, false y null. json.dumps() gestiona este mapeo automáticamente: True se convierte en true, False en false y None en null. No necesitas convertirlos manualmente. En sentido contrario, json.loads() los mapea de vuelta a tipos Python.

¿Cómo gestiono objetos datetime al convertir datos CSV a JSON?

Pasa una función default= a json.dumps() que convierta los objetos datetime a cadenas ISO 8601. La función default se llama para cualquier objeto que json no puede serializar de forma nativa. Devuelve obj.isoformat() para instancias datetime y lanza TypeError para cualquier otro tipo.

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"}

¿Puedo convertir CSV a JSON sin pandas?

Sí. La biblioteca estándar de Python tiene todo lo que necesitas. Usa csv.DictReader para leer cada fila como un diccionario, recoge las filas en una lista y serializa con json.dump() o json.dumps(). No se requieren bibliotecas de terceros. Pandas solo vale la pena añadirlo si también necesitas limpieza de datos, inferencia de tipos o ya lo usas en otra parte del proyecto.

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)

Para una alternativa con un solo clic sin escribir nada de Python, prueba el conversor CSV a JSON — pega tus datos CSV y obtén JSON formateado de inmediato.

Herramientas Relacionadas

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 SharmaRevisor técnico

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.