Cookies de estadística y publicidad
Usamos cookies de estadística y de publicidad, y ambas van a Google. Si rechazas, para ti no cambia nada visible.Ir a la página de privacidad
Aquí puedes convertir NDJSON a TSV gratis y sin cuenta: suelta el archivo arriba y en un par de segundos tienes el resultado listo para descargar. La conversión ocurre en tu propio navegador, así que el archivo no se sube nunca. Funciona igual en Windows, macOS y Linux que en iPhone y Android, y sigue funcionando aunque cortes la conexión.
Hasta 100 archivos a la vez. Mezclar formatos no es problema.
Se convierten uno tras otro y vuelven juntos en un ZIP.
NDJSON a TSV
Mira qué contiene de verdad un registro de evento. Una ruta con su cadena de consulta. Un identificador de navegador, que no es más que comas y paréntesis. Un mensaje de error citando un valor. Una dirección postal, donde la coma separa la calle del número y el número del piso. Manda eso a un CSV y una parte enorme de cada fila acaba entre comillas, porque el delimitador aparece dentro de los datos en casi todas las líneas.
Los tabuladores no aparecen prácticamente nunca dentro de esos valores, así que la mayoría de campos se escriben desnudos y el archivo sigue siendo posicional: la columna tres está de verdad entre el segundo y el tercer tabulador. Esa es la propiedad de la que trata el resto de la página, y también la que un puñado de campos te puede quitar sin avisar.
Conviene ser exacto con lo que hace el escritor, porque toda la gracia de un archivo separado por tabuladores es que quien lo lee puede ser rudimentario. Un valor que contiene un tabulador se envuelve entre comillas dobles. Un valor que contiene una comilla doble se envuelve, y la comilla interior se dobla. Un valor que contiene un salto de línea se envuelve. Todo lo demás, comas incluidas, se escribe tal cual.
Es la convención de un CSV con el tabulador en el papel de la coma, y no es la definición formal de «valores separados por tabuladores», que prohíbe el tabulador dentro de un campo en lugar de escaparlo. La consecuencia práctica es que cortar por el cuarto campo funciona hasta que un mensaje de registro contiene un tabulador; a partir de esa fila, y solo en esa fila, hay una columna de más y todo lo posterior se desplaza. Nada da error. Si tus campos pueden llevar texto pegado por una persona —y los mensajes de error lo llevan—, valida antes de fiarte de una lectura por posición o usa un lector que entienda comillas.
Las columnas son la unión de todas las claves que aparecen en cualquier punto del archivo, en el orden en que cada una se vio por primera vez. Es la respuesta correcta para un origen en el que nada obliga a la segunda línea a traer las claves de la primera, y es lo más importante que hay que entender antes de automatizar esta conversión.
Significa que el orden de columnas es una propiedad de los datos y no del formato. Una exportación nocturna en la que el primer registro de error aparece hoy en la línea 12 y mañana en la 40.000 produce dos archivos con las columnas en distinto orden. La fila de cabecera es correcta en los dos. Un proceso que lee por nombre no se entera; uno que lee por posición está equivocado desde el segundo día y no da ninguna señal.
La solución consiste en dejar de permitir que decida el archivo. Proyecta los registros a un juego fijo de claves antes de convertir: recorrer el NDJSON con jq y quedarte con las cuatro o cinco claves que te interesan, en el mismo orden siempre, deja a la conversión una sola disposición posible de columnas pase lo que pase en el origen.
Eso resuelve al mismo tiempo el problema de la tabla ancha y vacía. Una exportación con eventos de varios tipos convertida entera produce una columna por cada campo que cualquier tipo de evento haya llevado alguna vez, la mayoría vacías en la mayoría de filas; proyectando antes obtienes una tabla estrecha y sin huecos. Si no puedes proyectar, al menos comprueba: lee la línea de cabecera dentro del proceso y falla ruidosamente si no es la que esperabas, en lugar de dejar que una lectura por posición devuelva el campo equivocado durante un mes.
Los registros estructurados anidan: un objeto de petición con su método y su ruta, un objeto de usuario con un identificador, un bloque de contexto con una traza. Cada hoja recibe una columna llamada como su ruta, con los tramos separados por puntos, y los índices de un arreglo cuentan como tramos. Una columna por valor final, sin excepciones.
Ese aplanado se aplica al ir hacia CSV, TSV, SQL, INI, XLSX y Parquet, y no se aplica al escribir JSON, YAML, TOML, XML ni NDJSON, que conservan el árbol. Un punto en el nombre de columna es inofensivo para las herramientas que parten por un carácter, porque nunca miran la cabecera, e incómodo en todo lo demás: hay que entrecomillarlo en SQL y no es un identificador válido en muchos cargadores. Si el TSV va a acabar en una tabla, renombra durante la proyección y no después, que ahorra una alteración de esquema más tarde.
Un número en JSON se escribe con punto decimal por definición del formato; no hay otra manera de escribirlo. Aquí ese valor no se reformatea ni se localiza: sale al TSV exactamente como venía, de modo que un importe de 1234.56 sigue siendo 1234.56 en el archivo. Eso es lo correcto y es también la trampa.
Abre ese TSV en una hoja de cálculo configurada para España o para casi cualquier país hispanohablante y la columna deja de ser numérica, porque ahí el separador decimal es la coma. Según la versión y la configuración, el valor se queda como texto alineado a la izquierda o, peor, algo con pinta de fecha se convierte en una fecha. La solución no es tocar el archivo: es decirle al lector cuál es la convención en el momento de importar —en el asistente de importación, o con la opción de punto decimal correspondiente si el destino es R o pandas—. Sustituir puntos por comas en masa reescribiría además cualquier punto que hubiera dentro de las columnas de texto.
Merece la pena distinguir este par de su vecino, el que convierte un CSV a TSV, porque se comportan distinto y la diferencia es útil. Allí el archivo se analiza como tabla y todo lo que parece un número se lee como número, con lo que un código postal como 08001 pierde su cero. Aquí no ocurre: cada línea se interpreta como JSON, y si el origen declaró esa clave como cadena, cadena sigue siendo. El TSV recibe 08001 con su cero delante.
Lo que no puede hacer el archivo es defenderse de lo que venga después. Un texto delimitado no distingue el número 7 de la cadena «7», así que el cargador de destino volverá a adivinar el tipo por su cuenta y ahí es donde se pierde el cero, se convierte un DNI en notación científica o un identificador largo se redondea. Si el destino permite declarar los tipos de columna, decláralos; es la única defensa real, y es más barata que descubrirlo con la tabla cargada.
Un null de JSON y una cadena vacía de JSON acaban los dos como nada entre dos tabuladores, y después no hay forma de distinguirlos. Tampoco es que el escritor sea descuidado: un archivo de texto delimitado no tiene un tercer estado en el que ponerlos.
Que importe depende de la pregunta que vayas a hacer. Contar cuántos eventos no traían identificador de usuario es una consulta distinta de contar cuántos lo traían vacío, y después de esta conversión las dos dan el mismo resultado. Si la distinción sostiene algo, codifícala antes de convertir con un valor centinela feo y sin ambigüedad, o manda la exportación a Parquet, donde el nulo es un estado real y la columna conserva su tipo.
PostgreSQL es el que exige cuidado, porque su formato de copia por defecto usa escapes con barra invertida en lugar de comillas y leería un campo entrecomillado de forma literal, comillas incluidas. Lo que encaja con lo que se ha escrito aquí es pedirle explícitamente el formato CSV con el tabulador como delimitador y la primera fila como cabecera; con eso las reglas de entrecomillado coinciden y no hay sorpresas.
DuckDB lo lee indicando el delimitador y la cabecera, e infiere los tipos a partir de una muestra, cosa muy cómoda y que es también la manera de que una columna de identificadores pierda sus ceros iniciales: pásale un mapa de tipos explícito para todo lo que deba seguir siendo texto. SQLite necesita fijar antes el separador y después importar. En los tres, un campo vacío llega como cadena vacía y no como nulo mientras no digas lo contrario, que es justo el problema de la sección anterior visto desde el otro extremo.
Las líneas en blanco se saltan, incluida la que casi todo el mundo deja al final del archivo, así que el número de filas de datos es el de líneas con contenido; súmale una por la cabecera para comparar con lo que te diga un contador de líneas. Es una comprobación de treinta segundos y detecta la mitad de los problemas de una exportación.
Una línea que no sea JSON válido no se descarta en silencio: detiene la conversión indicando el número de línea. Es deliberado y es lo que quieres en un proceso automatizado, porque una exportación truncada a mitad de escritura produce exactamente eso —una última línea incompleta—, y convertirla sin más te daría un archivo con una fila menos y ninguna señal de que faltaba algo.
Normalmente menos del que entró. Cada línea del origen repite los nombres de sus claves; el TSV los escribe una sola vez en la cabecera y a partir de ahí solo valores, de modo que un conjunto estrecho de registros suele encoger de forma apreciable. Uno ancho y disperso va en la otra dirección, porque cada fila tiene que llevar un tabulador por cada columna, incluidas aquellas en las que no tiene nada.
El techo formal son 100 MB por archivo, y lo que te encuentras primero es la memoria: para saber cuáles son las columnas hay que haber leído todos los registros, así que la tabla entera existe a la vez antes de escribir nada. Un NDJSON se puede partir con seguridad por cualquier salto de línea, y trocearlo produce archivos que convierten limpiamente cada uno; ten en cuenta que los trozos convertidos por separado pueden discrepar en el orden de columnas por el motivo de más arriba, que es un argumento más para proyectar primero.
JavaScript corriente dentro de esta página. No hay subida, ni descarga de ningún motor, ni cuenta, ni cupo diario; y la pestaña de red del navegador durante una conversión es la forma de comprobarlo en lugar de creerse esta frase. Las líneas se separan además con un único salto de línea y no con la pareja de Windows, que es lo que esperan una tubería de shell, una diferencia de Git, R y pandas.
Las exportaciones de producción son el material para el que existe este par, y llevan direcciones IP, identificadores de sesión, rutas de petición e identificadores de navegador. Entregar una a un conversor alojado es una comunicación de datos a un tercero, prometa lo que prometa ese conversor y esté donde esté su servidor. Aquí no hay ninguna comunicación sobre la que razonar.
| NDJSON | TSV | |
|---|---|---|
| Nombre completo | Newline-Delimited JSON | Tab-Separated Values |
| Extensión de archivo | .ndjson, .jsonl | .tsv, .tab |
| Tipo de medio | application/x-ndjson | text/tab-separated-values |
| Publicado por primera vez | 2013 | 1993 |
| Especificación | — | IANA text/tab-separated-values |
| Licencia | Estándar abierto | Estándar abierto |
| Situación actual | Vigente | Vigente |
| Se abre en el navegador | Ningún navegador | Ningún navegador |
| Considerado en su lugar | JSON, CSV | CSV, JSON |
pandas lee tanto NDJSON como TSV, así que puedes comparar el resultado con el original sin un segundo programa.
TSV es de 1993, recogido en IANA text/tab-separated-values. Microsoft Excel, LibreOffice Calc y pandas lo leen.
TSV se publicó en 1993 y NDJSON en 2013. El más antiguo suele ser el archivo más seguro para entregar; el más reciente hace lo mismo con menos bytes.
No. Esta conversión ocurre por completo en tu navegador, así que el archivo no sale de tu dispositivo. Puedes comprobarlo tú: abre la pestaña de red de las herramientas de desarrollo y convierte algo. Verás la propia página y las peticiones de estadística y publicidad con las que se paga este servicio, y ni una sola que lleve tu archivo.
Sí. Sin cuenta, sin marca de agua y sin cupo diario que se gaste: se ejecuta en tu propio equipo, así que puedes volver tantas veces como quieras. El navegador procesa archivos de hasta 100 MB, 100 a la vez.
NDJSON y TSV describen el contenido de maneras radicalmente distintas. La conversión es por tanto una reconstrucción y no una copia: fiel, pero no idéntica byte a byte. Los objetos anidados se aplanan en columnas. Los datos muy anidados pierden su forma.
Para la conversión no: ocurre en el navegador que ya tienes abierto. Para abrir el resultado necesitas después el programa con el que tu dispositivo muestra normalmente Tab-Separated Values.