Skip to content
Volver al blog
Tutoriales

CSV a JSON: Métodos, errores comunes y ejemplos de código

Aprende a convertir CSV a JSON (y viceversa) con Python, JavaScript y herramientas CLI. Cubre problemas de codificación, coerción de tipos, estructuras anidadas y streaming de archivos grandes.

12 min de lectura

Guía de conversión de CSV a JSON: métodos, errores comunes y buenas prácticas

Tu equipo de operaciones te envía una exportación en CSV. Tu API espera JSON. Abres el archivo, miras 10,000 filas de valores separados por comas y te preguntas: ¿cuál es la forma más rápida de convertir CSV a JSON sin perder datos?

Esta guía cubre cuatro métodos de conversión (herramientas en el navegador, JavaScript, Python, CLI), la dirección inversa (JSON a CSV), cinco errores comunes que corrompen tus datos silenciosamente, y cómo manejar archivos demasiado grandes para caber en memoria.

CSV vs JSON: ¿cuándo usar cada uno?

Antes de convertir, es útil entender en qué destaca cada formato.

DimensiónCSVJSON
EstructuraTabla plana (filas y columnas)Jerarquía anidada (objetos, arrays)
Tipos de datosTodo es una cadena de textostring, number, boolean, null
LegibilidadAmigable para hojas de cálculoAmigable para desarrolladores
Uso principalExportación/importación de datos, informes, ETLAPIs, archivos de configuración, almacenamiento NoSQL
Tamaño de archivoMás pequeño (sin nombres de clave repetidos)Más grande (los nombres de clave se repiten por registro)
EsquemaImplícito (fila de encabezado)Explícito (o usar JSON Schema)

Regla general: Usa CSV cuando tus datos son tabulares y el consumidor es una hoja de cálculo o un pipeline de datos. Usa JSON cuando tus datos tienen jerarquía o tu consumidor es una API. Siempre puedes validar tu salida JSON con un JSON Formatter para detectar problemas estructurales a tiempo.

Si tu proyecto usa formatos JSON relajados como JSON5 o JSONC para configuración, consulta nuestra guía de formato JSON5 y JSONC para conocer las diferencias de sintaxis y herramientas.

4 formas de convertir CSV a JSON

Método 1 — Herramienta en el navegador

Para conversiones puntuales, una herramienta basada en el navegador es el camino más rápido. Pega tu CSV en un convertidor en línea, obtiene JSON de salida, y luego valida el resultado en un JSON Formatter para confirmar que la estructura es correcta.

La ventaja: tus datos nunca salen de tu navegador. Sin subidas, sin procesamiento en servidor, sin preocupaciones de privacidad. Esto importa cuando trabajas con datos internos, claves de API incrustadas en exportaciones, o cualquier cosa que prefieras no enviar a un servidor de terceros.

Ideal para: archivos pequeños (menos de 10 MB), conversiones rápidas de una sola vez, y miembros del equipo no técnicos.

Método 2 — JavaScript / Node.js

Navegador (JavaScript puro):

function csvToJson(csv) {
  const lines = csv.trim().split('\n');
  const headers = lines[0].split(',').map(h => h.trim());

  return lines.slice(1).map(line => {
    const values = line.split(',');
    return headers.reduce((obj, header, i) => {
      obj[header] = values[i]?.trim() ?? '';
      return obj;
    }, {});
  });
}

const csv = `name,age,city
Alice,30,New York
Bob,25,London`;

console.log(JSON.stringify(csvToJson(csv), null, 2));

Esto funciona para CSV simple sin campos entrecomillados. Para uso en producción con comas dentro de valores, saltos de línea en campos o cadenas entrecomilladas, usa un parser adecuado.

Node.js (csv-parser + streams):

import { createReadStream } from 'fs';
import { parse } from 'csv-parse';

const records = [];

createReadStream('data.csv')
  .pipe(parse({ columns: true, trim: true, skip_empty_lines: true }))
  .on('data', (row) => records.push(row))
  .on('end', () => {
    console.log(JSON.stringify(records, null, 2));
  });

La opción columns: true usa la primera fila como claves. La opción trim elimina los espacios en blanco de los valores. Esto maneja correctamente campos entrecomillados, comas escapadas y valores multilínea.

Método 3 — Python

Biblioteca estándar (sin dependencias):

import csv
import json

with open('data.csv', encoding='utf-8') as f:
    reader = csv.DictReader(f)
    rows = list(reader)

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

csv.DictReader mapea cada fila a un diccionario usando la fila de encabezado como claves. La opción ensure_ascii=False preserva los caracteres Unicode (chino, japonés, caracteres acentuados) en lugar de escaparlos como \uXXXX.

Pandas (una sola línea para científicos de datos):

import pandas as pd

df = pd.read_csv('data.csv')
df.to_json('data.json', orient='records', indent=2, force_ascii=False)

Cuándo usar cada uno:

  • csv + json: Scripts ligeros, funciones Lambda, contenedores donde quieres dependencias mínimas.
  • pandas: Cuando también necesitas limpiar, filtrar o transformar datos antes de convertir. La sobrecarga de importar pandas vale la pena cuando haces más que solo conversión de formato.

Método 4 — Herramientas CLI

Para scripts de shell y pipelines de automatización:

csvkit:

# Install: pip install csvkit
csvjson data.csv > data.json

Miller (mlr):

# Install: brew install miller (macOS) or apt install miller (Ubuntu)
mlr --csv --json cat data.csv > data.json

Combinar con jq para filtrar:

# Convert and filter in one pipeline
csvjson data.csv | jq '[.[] | select(.age | tonumber > 25)]'

Miller es particularmente potente porque maneja CSV, JSON, TSV y otros formatos de forma nativa. Puedes transformar datos durante la conversión:

# Convert CSV to JSON, rename a field, add a computed field
mlr --csv --json rename name,fullName then put '$age_group = ($age > 30) ? "senior" : "junior"' data.csv

JSON a CSV: manejar la dirección inversa

Convertir JSON a CSV introduce desafíos que no existen en la dirección directa.

Aplanar objetos anidados

CSV es inherentemente plano. Cuando tu JSON tiene objetos anidados, necesitas una estrategia de aplanamiento:

{
  "name": "Alice",
  "address": {
    "city": "New York",
    "zip": "10001"
  }
}

Se convierte en:

nameaddress.cityaddress.zip
AliceNew York10001

La convención de notación con puntos (address.city) es el enfoque más común. En Python:

import pandas as pd

data = [
    {"name": "Alice", "address": {"city": "New York", "zip": "10001"}},
    {"name": "Bob", "address": {"city": "London", "zip": "EC1A"}}
]

df = pd.json_normalize(data)
df.to_csv('output.csv', index=False)
# Columns: name, address.city, address.zip

Manejo de arrays

Los campos de tipo array requieren una decisión:

EstrategiaEntrada de ejemploSalida CSVIdeal para
Unir como cadena["admin","editor"]admin;editorListas simples, reimportables
Expandir a columnas["admin","editor"]role_0: admin, role_1: editorArrays de longitud fija
Expandir a filas["admin","editor"]Dos filas, una por rolAnálisis relacional

Elige según tu consumidor final. Si el CSV va de vuelta a una base de datos, expandir a filas suele tener más sentido.

Pérdida de información de tipos

CSV no tiene sistema de tipos. Cuando conviertes JSON a CSV:

  • true se convierte en la cadena "true" — ¿es un booleano o una cadena?
  • null se convierte en una celda vacía — indistinguible de una cadena vacía ""
  • 42 se convierte en "42" — ¿es un número o una cadena?

Si la fidelidad de ida y vuelta es importante (CSV -> proceso -> JSON), documenta tus convenciones de tipos en un comentario de encabezado o en un archivo de esquema complementario.

5 errores comunes y cómo evitarlos

Estos problemas corrompen datos silenciosamente. La mayoría de los tutoriales los omiten. No los aprendas en producción.

1. Trampas de codificación

El problema: Abres un CSV de un colega y ves é en lugar de é, o 锟斤拷 en lugar de caracteres chinos.

Por qué ocurre: El archivo fue guardado en una codificación (Windows-1252, GBK, Shift_JIS) pero tu parser asume UTF-8. Excel en Windows a menudo guarda CSV como Windows-1252 o agrega un BOM UTF-8 (Byte Order Mark — el invisible \xEF\xBB\xBF al inicio del archivo).

La solución:

# Detect encoding first
import chardet

with open('data.csv', 'rb') as f:
    result = chardet.detect(f.read(10000))
    print(result)  # {'encoding': 'Windows-1252', 'confidence': 0.73}

# Then read with the correct encoding
with open('data.csv', encoding=result['encoding']) as f:
    reader = csv.DictReader(f)
    # ...

En Node.js, elimina el BOM explícitamente:

import { readFileSync } from 'fs';

let content = readFileSync('data.csv', 'utf-8');
// Strip UTF-8 BOM if present
if (content.charCodeAt(0) === 0xFEFF) {
  content = content.slice(1);
}

2. Confusión de delimitadores

El problema: Tu parser produce una sola columna gigante en lugar de múltiples campos.

Por qué ocurre: En muchas configuraciones regionales europeas y latinoamericanas (Francia, Alemania, España, países de América Latina), Excel usa punto y coma (;) como delimitador de CSV porque las comas se usan como separadores decimales (por ejemplo, 3,14 en lugar de 3.14). Los archivos separados por tabulaciones (.tsv) agregan otra variante.

La solución: Detectar automáticamente el delimitador muestreando las primeras líneas:

import csv

with open('data.csv') as f:
    sample = f.read(8192)
    dialect = csv.Sniffer().sniff(sample, delimiters=',;\t|')
    f.seek(0)
    reader = csv.DictReader(f, dialect=dialect)

3. Los ceros iniciales desaparecen

El problema: El código postal 00501 se convierte en 501. El código de producto 007 se convierte en 7.

Por qué ocurre: El parser (o Excel) interpreta el campo como un número y elimina los ceros iniciales. Esto es especialmente peligroso con códigos postales, números de teléfono y códigos de identificación.

La solución: Forzar el tipo cadena. En pandas:

df = pd.read_csv('data.csv', dtype={'zip': str, 'product_code': str})

En JavaScript, verificar si la cadena original difiere de su conversión numérica:

function preserveLeadingZeros(value) {
  if (/^0\d+$/.test(value)) return value; // Keep as string
  const num = Number(value);
  return isNaN(num) ? value : num;
}

4. Pérdida de precisión en números grandes

El problema: El ID 9007199254740993 se convierte en 9007199254740992 en tu JSON.

Por qué ocurre: El tipo Number de JavaScript es un flotante de 64 bits (IEEE 754). Los enteros por encima de Number.MAX_SAFE_INTEGER (2^53 - 1 = 9007199254740991) pierden precisión. Esto afecta a IDs de bases de datos, Snowflake IDs y IDs de publicaciones de Twitter/X.

La solución: Mantener los números grandes como cadenas en JSON, o usar BigInt en tu código de procesamiento:

// Parse with string preservation for large numbers
function safeParseNumber(value) {
  const num = Number(value);
  if (Number.isInteger(num) && !Number.isSafeInteger(num)) {
    return value; // Keep as string to preserve precision
  }
  return isNaN(num) ? value : num;
}

5. Ambigüedad de valores vacíos

El problema: Tu CSV tiene celdas vacías. Después de la conversión, no puedes saber si el valor original era una cadena vacía "", null, o simplemente estaba ausente.

Por qué ocurre: CSV no tiene forma de distinguir entre estos tres estados. Un campo vacío entre dos comas (Alice,,30) podría significar cualquiera de ellos.

La solución: Define una convención y aplícala de forma consistente:

def parse_value(value):
    if value == '':
        return None        # or '' — pick one convention
    if value == 'NULL' or value == 'null':
        return None
    return value

Si tus datos usan valores centinela como NULL, N/A o -, documéntalos y manéjalos explícitamente.

Streaming de archivos grandes

Cuando tu CSV supera los 100 MB, cargarlo completamente en memoria no es una opción. Usa streaming.

Node.js (pipeline de streams):

import { createReadStream, createWriteStream } from 'fs';
import { parse } from 'csv-parse';
import { Transform } from 'stream';
import { pipeline } from 'stream/promises';

let first = true;
const toJsonArray = new Transform({
  objectMode: true,
  transform(record, encoding, callback) {
    const prefix = first ? '[\n' : ',\n';
    first = false;
    callback(null, prefix + JSON.stringify(record));
  },
  flush(callback) {
    callback(null, '\n]');
  }
});

await pipeline(
  createReadStream('large.csv'),
  parse({ columns: true, trim: true }),
  toJsonArray,
  createWriteStream('large.json')
);

Python (generador):

import csv
import json

def csv_rows(path):
    with open(path, encoding='utf-8') as f:
        reader = csv.DictReader(f)
        for row in reader:
            yield row

# Stream to JSON Lines format (one JSON object per line)
with open('large.jsonl', 'w', encoding='utf-8') as out:
    for row in csv_rows('large.csv'):
        out.write(json.dumps(row, ensure_ascii=False) + '\n')

Para archivos muy grandes, considera JSON Lines (.jsonl) en lugar de un único array JSON. Cada línea es un objeto JSON independiente, lo que significa que también puedes procesar el archivo de salida línea por línea, sin necesidad de parsear todo el contenido.

Preguntas frecuentes

¿Cuál es la diferencia entre CSV y JSON?

CSV (Comma-Separated Values) almacena datos como una tabla plana donde cada valor es una cadena de texto. JSON (JavaScript Object Notation) almacena datos estructurados con objetos anidados, arrays y valores tipados (cadenas, números, booleanos, null). CSV es más pequeño y amigable para hojas de cálculo; JSON es más expresivo y amigable para APIs.

¿Cómo convierto CSV a JSON en JavaScript?

Usa el paquete csv-parse en Node.js: lee el archivo con createReadStream, pásalo por parse({ columns: true }) y recopila los resultados. Para uso en el navegador, lee el archivo con FileReader, divide por saltos de línea y mapea las filas a objetos usando la fila de encabezado como claves.

¿Cómo convierto CSV a JSON en Python?

Usa csv.DictReader de la biblioteca estándar para leer filas como diccionarios, luego json.dump() para escribirlas como un array JSON. Para manipulación de datos antes de la conversión, pandas.read_csv() seguido de df.to_json(orient='records') es una alternativa de una sola línea.

¿Se puede convertir JSON anidado a CSV?

Sí, pero necesitas una estrategia de aplanamiento. El enfoque más común usa notación con puntos: un campo como address.city se convierte en un encabezado de columna. En Python, pandas.json_normalize() maneja esto automáticamente. Los arrays requieren decisiones adicionales: unir como cadenas, expandir a columnas o expandir a filas.

¿Por qué mi CSV tiene caracteres ilegibles después de la conversión?

Discrepancia de codificación. El archivo probablemente fue guardado en Windows-1252 o GBK, pero tu parser asume UTF-8. Usa una biblioteca de detección como chardet (Python) para identificar la codificación, luego especifícala explícitamente al leer. También verifica si hay un BOM UTF-8 que algunas herramientas agregan automáticamente.

¿Cómo manejo un archivo CSV de más de 100 MB?

Usa streaming en lugar de cargar el archivo completo en memoria. En Node.js, pásalo por csv-parse con streams. En Python, itera con csv.DictReader usando un generador. Considera generar formato JSON Lines (.jsonl) en lugar de un único array JSON para facilitar el procesamiento posterior.

¿Cómo puedo verificar que mi JSON convertido es válido?

Pega la salida en un JSON Formatter en línea para verificar sintaxis, estructura y anidamiento. Para validación automatizada, usa JSON.parse() en JavaScript o json.loads() en Python — ambos lanzan errores claros ante entrada inválida. Para validación de esquema, define un JSON Schema y valida programáticamente.

Conclusiones clave

  1. Elige el método adecuado para tu contexto: herramientas en el navegador para conversiones puntuales, código para automatización, CLI para pipelines.
  2. Cuidado con los problemas de codificación — siempre especifica la codificación explícitamente en lugar de depender de los valores por defecto.
  3. Preserva los tipos intencionalmente — los ceros iniciales, los enteros grandes y los valores nulos necesitan manejo explícito.
  4. Usa streaming para archivos grandes en lugar de cargarlos en memoria. Considera el formato JSON Lines para conjuntos de datos muy grandes.
  5. Valida tu salida — pasa el JSON convertido por un JSON Formatter para detectar problemas estructurales antes de que lleguen a producción.

Artículos relacionados

Ver todos los artículos