Convertir JSON a CSV sin perder el significado de los datos
JSON y CSV resuelven problemas distintos. JSON conserva objetos, listas y tipos; CSV ordena valores en filas y columnas. Convertir entre ambos puede ser muy práctico para abrir un extracto en una hoja de cálculo, pero nunca es una operación neutral. Antes de pulsar convertir conviene decidir qué representa una fila, qué campos se van a aplanar, qué tipos se escribirán como texto y qué información no podrá reconstruirse.
El error más común es tratar CSV como si fuese “JSON sin llaves”. RFC 8259 permite estructuras anidadas, valores null, booleanos, números y cadenas. RFC 4180 describe registros delimitados con comas, donde los campos con coma, comillas o salto de línea se entrecomillan y las comillas internas se duplican. No hay una regla universal que indique cómo una lista de pedidos debe caber en una sola fila. Esa decisión pertenece al contrato de exportación.
El problema
El problema aparece cuando una exportación mezcla datos que tienen distinta cardinalidad. Una persona puede tener un cliente, una dirección y muchos pedidos; cada pedido puede contener muchas líneas. Si cada cliente ocupa una fila, ¿dónde se guardan dos pedidos? Si cada línea ocupa una fila, ¿se repiten el cliente y el pedido? Ambas opciones son válidas para usos distintos, pero generan archivos con significado diferente.
También hay riesgos de tipo. Un identificador como "00073" no es el número 73: sus ceros pueden ser parte del código. Una celda que contiene true puede ser un booleano o una cadena literal según el importador. null significa ausencia de valor, mientras que una cadena vacía puede significar “se conoce y está vacía”. Si estos casos se convierten todos en una celda vacía, la hoja resulta legible pero pierde información necesaria para una importación posterior.
El delimitador tampoco elimina la necesidad de escapado. Una nota como Entregar en Madrid, puerta 4 contiene una coma y debe ir entre comillas. Una nota con dos líneas debe conservar el salto de línea dentro de un campo entrecomillado. Abrir el archivo y verlo bien en una aplicación no prueba que otro importador use las mismas reglas de codificación, delimitador o saltos de línea.
Ejemplo práctico
Usa un ejemplo sintético y pequeño, no datos de clientes reales. Este JSON reúne un cliente, dos pedidos, una lista de etiquetas, un valor nulo, un booleano, códigos con ceros iniciales, una coma y un salto de línea.
{
"customer": {
"id": "00073",
"name": "Lucía, S.A.",
"marketingAllowed": false,
"phone": null,
"tags": ["mayorista", "prioridad"],
"address": { "city": "Madrid", "postalCode": "08001" }
},
"orders": [
{ "id": "ORD-001", "paid": true, "note": "Llamar antes de entregar\npor la tarde", "items": [{ "sku": "A-01", "qty": 2 }, { "sku": "B-02", "qty": 1 }] },
{ "id": "ORD-002", "paid": false, "note": "Entrega en Valencia, recepción", "items": [{ "sku": "C-03", "qty": 4 }] }
]
}
Una exportación de una fila por línea de pedido puede producir columnas customer.id, customer.name, customer.marketingAllowed, customer.phone, customer.address.city, customer.address.postalCode, order.id, order.paid, order.note, item.sku e item.qty. La primera fila tendría "00073", "Lucía, S.A.", false, una celda vacía, Madrid, "08001", ORD-001, true, una nota entrecomillada con salto de línea, A-01 y 2. La información del cliente se repite porque cada fila representa una línea, no un cliente.
Procedimiento
Primero define la unidad de la fila con una frase que otra persona pueda comprobar: “cada fila es una línea de pedido” o “cada fila es un pedido”. Después enumera las rutas JSON que serán columnas, usando una notación estable como customer.address.postalCode. Evita encabezados vagos como id, que se vuelven ambiguos al añadir un identificador de cliente y otro de pedido.
El siguiente paso es decidir qué hacer con cada array. Para orders e items, una estrategia normalizada genera una fila por combinación pedido-línea y repite los campos de nivel superior. Es la opción más útil para filtrar cantidades y sumar ventas. Si el destino necesita una fila por pedido, items puede serializarse como JSON en una columna, pero entonces CSV ya no describe todas las propiedades por separado. Para tags, documenta si crearás tags con valores unidos por ;, varias columnas numeradas o una tabla separada. No inventes un separador si una etiqueta puede contenerlo.
Después fija la representación de tipos. Conserva identificadores y códigos postales como texto; al importar en una hoja, selecciona la columna de texto antes de que convierta 00073 en 73. Representa los booleanos con true y false o con una pareja acordada, nunca mezclando Sí, 1 y true. Elige una señal explícita para null, por ejemplo una columna vacía acompañada de una especificación que diferencie nulo y vacío, o un valor reservado que no pueda aparecer como dato. Prueba la exportación con caracteres no ASCII, comas, comillas y saltos de línea.
Por último, valida el resultado con un lector CSV conforme al formato acordado. Comprueba el número de filas esperado: en el ejemplo son tres líneas de pedido. Revisa que una comilla se exporte como dos comillas dentro de un campo entrecomillado y que el salto de línea no cree un registro adicional. La herramienta de conversión puede preparar el archivo; el contrato sigue siendo responsabilidad de quien lo integra.
Explicación técnica
El aplanamiento transforma rutas de un árbol en nombres de columna. customer.address.city conserva el camino, pero no convierte una estructura jerárquica en algo reversible por sí solo. Las rutas de objetos son relativamente directas porque cada objeto aporta una sola propiedad por clave. Los arrays cambian la relación: una lista contiene cero, uno o muchos valores y una tabla necesita elegir entre repetir filas, agrupar valores o crear otra tabla.
La estrategia de repetir filas se parece a separar tablas relacionadas en una base de datos. Para cada línea de orders[0].items, se copian los valores de customer y de orders[0]. Así se puede calcular el total de unidades sin analizar una celda JSON. El coste es la duplicación. Si se modifica el nombre del cliente en una sola fila, las filas dejan de coincidir. Por eso CSV suele ser un formato de intercambio o análisis, no la única fuente de verdad.
RFC 4180 exige comillas alrededor de campos que contienen comas, comillas o saltos de línea; una comilla de datos se representa duplicándola. No uses una sustitución simple de comas por punto y coma: eso cambia el contenido y falla si el destino espera comas. También aclara la codificación y el carácter de fin de línea, porque CSV no contiene metadatos fiables para todas las decisiones de importación.
Errores frecuentes
Un fallo frecuente es elegir la primera lista y descartar las demás. Convertir el ejemplo a una fila por pedido y guardar solo el primer item convierte una exportación aparentemente correcta en una pérdida silenciosa. Otro es concatenar valores con coma sin escaparlos: Lucía, S.A. pasa a parecer dos columnas. Un tercer fallo es usar una columna vacía tanto para null como para ""; al volver a JSON no hay forma de saber qué valor había.
También falla asumir que una hoja de cálculo preserva tipos. Puede convertir 00073 a 73, interpretar ORD-001 como fecha según la configuración local o mostrar números grandes con notación científica. Si el archivo se reimportará, entrega una especificación de columnas y una muestra de prueba. Guarda además un JSON original o un identificador de lote para poder localizar la fuente.
Finalmente, no confundas un CSV bien formado con datos seguros. Una celda que empieza por =, +, - o @ puede tratarse como fórmula al abrirla en ciertos programas. Si exportas texto controlado por usuarios para hojas de cálculo, aplica una política explícita de mitigación compatible con el destino y verifica el resultado. No resuelvas ese riesgo cambiando sin aviso los datos de una integración crítica.
Consideraciones
Antes de diseñar columnas pregunta quién leerá el archivo. Para análisis puntual, una tabla ancha y repetida puede ser útil. Para una migración, quizá sean preferibles varios CSV relacionados: clientes, pedidos y líneas, unidos por identificadores textuales. Para una copia de seguridad, JSON conserva mucho mejor la estructura original. El mismo conjunto de datos puede requerir tres exportaciones distintas sin que ninguna sea “la conversión correcta”.
Escribe una tabla de mapeo junto al exportador: ruta JSON, columna CSV, tipo esperado, transformación, tratamiento de nulo y ejemplo. Incluye casos límite, como una lista vacía, una nota que contiene comillas y un cliente sin teléfono. Versiona el mapeo cuando cambies una columna. Un consumidor que depende de customer.id no debería descubrir por casualidad que ahora se llama client_code.
La privacidad también condiciona la conversión. Reducir campos antes de exportar suele ser más seguro que ocultarlos después en una hoja compartida. El ejemplo usa información inventada precisamente para que sea reutilizable. Si el archivo contiene datos personales, limita el acceso, evita subirlo a servicios que no hayas evaluado y sigue las obligaciones aplicables a la organización responsable.
Limitaciones
No existe una conversión JSON→CSV que preserve automáticamente todos los significados de cualquier documento. CSV no distingue por sí mismo entre número y texto, null y vacío, objeto ausente y objeto vacío, o lista de un elemento y texto que parece una lista. Un archivo de ida y vuelta puede reconstruir algunas filas si guarda reglas adicionales, pero no el árbol original en todos los casos.
Esta guía no certifica compatibilidad con una hoja concreta, ni sustituye el contrato de una API, pruebas de integración o asesoramiento profesional sobre datos regulados. El comportamiento de importación depende del programa, la configuración regional y la codificación. Prueba siempre con copias sintéticas y verifica el destino real antes de procesar un lote importante.
Lista de comprobación
Define qué representa una fila y qué rutas JSON serán columnas. Elige una estrategia para cada array y documenta sus duplicaciones. Conserva identificadores con ceros iniciales como texto. Define de forma inequívoca booleanos, null y cadena vacía. Escapa comas, comillas y saltos de línea conforme a CSV. Prueba con el JSON sintético, cuenta las filas y vuelve a leer el archivo con el consumidor previsto. Conserva el JSON original cuando necesites fidelidad estructural, y publica un mapeo versionado para que otra persona pueda reproducir la exportación.