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 Parquet 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 Parquet
Es lo que hace interesante a este par. Cada línea de un NDJSON es independiente, y precisamente por eso es el formato al que las cosas añaden: se puede meter un campo nuevo en el emisor un martes sin reescribir ni una sola línea de las anteriores. Al cabo de unos meses de despliegues, un mismo fichero acumula tres o cuatro formas distintas de registro conviviendo en orden cronológico.
Parquet no tolera nada de eso. Su pie de página declara un conjunto fijo de columnas con un tipo cada una y todas las filas lo obedecen, que es justamente lo que permite a un motor de consultas describir un fichero de dos gigabytes sin leer una fila. Así que la conversión tiene que reconciliar esas generaciones en un solo esquema, y todo lo que sigue es consecuencia de cómo lo hace.
Un campo que aparece por primera vez trescientas mil líneas dentro del fichero se convierte igualmente en columna, y las filas anteriores reciben nulos. Es la única reconciliación que no puede perder datos, y es el motivo de que el lector recorra el fichero entero antes de escribir nada.
La mayoría de las herramientas hacen lo contrario: muestrean las primeras mil líneas o el primer megabyte. De ahí que una carga que funcionaba con un extracto de pruebas falle en producción, y el fallo es peor que un error, porque un esquema muestreado descarta en silencio todos los campos que no llegó a ver. Leerlo todo cuesta una pasada sobre los datos y elimina esa categoría entera de sorpresa.
Hay una variante de la deriva que sale mucho en sistemas escritos en español y migrados después. El emisor mandaba `importe`, `fecha` y `usuario`, alguien internacionalizó el proyecto y a partir de cierto despliegue manda `amount`, `date` y `user`. La unión hace exactamente lo que promete: seis columnas, cada una llena en su mitad del fichero y nula en la otra.
No es un fallo de la conversión y tampoco es algo que la conversión pueda arreglar sin adivinar, porque nada en los datos dice que las dos claves signifiquen lo mismo. Lo que sí puedes hacer es detectarlo en un vistazo: dos columnas casi complementarias en sus nulos son siempre el mismo campo bajo dos nombres, y unirlas es una sola expresión en la consulta o un `jq` antes de convertir.
La otra mitad de la deriva es una clave que conservó el nombre y cambió de tipo: un identificador que era numérico y ahora va entrecomillado, un estado que era booleano y pasó a ser una cadena, una versión que fue 3 y luego «3.1». Todos aparecen en ficheros de eventos de larga vida, normalmente sin que nadie se diera cuenta en su momento.
El tipo de cada columna se decide sobre todos sus valores: todos booleanos da booleano, todos enteros dentro del rango de 32 bits da entero, otros números dan coma flotante y cualquier mezcla da una columna de texto con los valores numéricos escritos como cadenas. Una columna de texto se ve, se convierte con una expresión y no tira ninguna fila; la alternativa —quedarse con el primer tipo y anular el resto— sí. Si una columna que esperabas numérica llega como texto, consultar los valores que fallan al convertir es la vía más rápida para encontrar el día en que cambió el emisor.
Los eventos estructurados anidan por convención: un bloque de petición, uno de usuario, un contexto con el identificador de traza. Parquet no tiene dónde meter un objeto dentro de una celda, así que cada registro se aplana hasta sus hojas y la ruta se convierte en el nombre de la columna: `request.method`, `user.id`, `context.trace_id`. Los tipos sobreviven a ese paso porque vienen del JSON y no de reinterpretar texto.
Las listas son el caso que conviene mirar antes de convertir. Se aplanan por posición, de modo que una lista de etiquetas con dos elementos produce `tags.0` y `tags.1`, y el conjunto de columnas es la unión de todo el fichero: una lista inusualmente larga en algún punto de un mes de eventos ensancha el esquema del mes entero. Donde un campo sea una lista de longitud genuinamente variable, unirla en una sola cadena con `jq` antes de convertir da un esquema que se puede consultar en vez de uno que hay que explicar.
Los enteros que se salen del rango de 32 bits no se escriben como enteros de 64 bits: se escriben en coma flotante de doble precisión, porque los valores llegaron hasta ahí como números de JavaScript, con 53 bits de precisión entera, y ponerlos como INT64 prometería una exactitud que ya no tienen. Los ficheros de eventos están llenos de valores a los que esto afecta.
Para una marca de tiempo en milisegundos desde 1970 no pasa nada: la precisión disponible está muy por encima de lo que un milisegundo necesita, y seguirá estándolo durante siglos. Para un identificador sí pasa, y el arreglo está en el emisor y no aquí: emitir los identificadores como cadenas JSON los mantiene exactos a lo largo de toda esta cadena y los deja como columna de texto, que es lo que un identificador debería ser de todas formas.
Hay una ironía de verdad en este par. NDJSON existe para que un consumidor no tenga que sostener el fichero entero, y esta conversión lo sostiene entero, porque la última línea puede añadir una columna o cambiar el tipo de una existente y el pie de página no se puede escribir hasta saberlo.
De modo que el techo es la memoria y no un nivel de suscripción: el límite por archivo son 100 MB, decenas de megabytes se convierten sin ceremonia y varios centenares es donde una pestaña empieza a sufrir. Por encima de eso el formato de origen juega a tu favor, porque partirlo por líneas produce ficheros válidos sin ninguna herramienta especial, cada uno se convierte por su cuenta y un motor de consultas lee un directorio de Parquet como una sola tabla.
La unidad natural de esta conversión es un periodo y no una historia completa: un día de eventos, un mes, un registro rotado. Cada uno se convierte en su propio fichero, y DuckDB, Spark y todos los formatos de tabla de lago leen un directorio de ellos como una sola tabla con los esquemas reconciliados en el momento de la lectura.
Eso además maneja la deriva mejor que un fichero único. Cuando cambia la forma del registro, los ficheros nuevos llevan las columnas nuevas y los viejos no, y quien reconcilia es el motor al leer en vez del conversor al escribir. Partir por día y convertir cada día una sola vez significa no tener que reconvertir toda la historia porque alguien añadió un campo.
DuckDB lee el fichero directamente en una cláusula FROM, pandas en una llamada y Spark como tabla nativa. Lo primero que merece la pena mirar no son las diez primeras filas sino la lista de columnas y sus tipos, con tres preguntas concretas: cuáles están casi siempre nulas, cuáles llegaron como texto debiendo ser números y cuántas columnas hay en total.
Cada respuesta es un hecho sobre el origen. Las columnas casi nulas marcan dónde cambió la forma del registro o dónde se renombró una clave; las de texto que deberían ser numéricas marcan dónde cambió un tipo bajo el mismo nombre; un número de columnas mayor que tu lista de campos marca un bloque anidado o una lista que se ensanchó más de lo que esperabas. Veinte segundos ahí ahorran la hora que cuesta descubrir cualquiera de las tres después de haber cruzado el fichero con otra cosa.
No vamos a decirte con qué códec queda comprimido el Parquet resultante. La conversión no pasa ninguna instrucción de compresión, así que lo que se aplique es el valor por defecto de la biblioteca que escribe, y en este proyecto no hay nada que lo fije ni ninguna prueba que lo sujete. Si tu plataforma exige un códec concreto, compruébalo leyendo los metadatos del fichero en lugar de fiarte de una frase.
Tampoco te vamos a prometer una relación de tamaños. Que un fichero por columnas encoja muchísimo frente a un NDJSON es esperable —cada línea del origen repite todos los nombres de campo y un almacén por columnas los escribe una vez, y los valores del mismo tipo juntos se comprimen mucho mejor que dispersos entre líneas—, pero el factor concreto depende por completo de tus datos: una columna de ciudades cuesta casi nada y una de texto libre irrepetible ahorra comparativamente poco.
El análisis del JSON y la escritura del Parquet los hace esta misma página; ninguna petición se lleva el fichero a ninguna parte, y la pestaña de red de las herramientas de desarrollo lo enseña mientras conviertes. No hay cuenta, ni cola, ni cupo diario que gastar: el contador diario de este sitio se aplica solo a las conversiones que ocurren en un contenedor nuestro, y esta no es una de ellas.
Para telemetría eso suele ser el factor que decide. Un flujo de eventos contiene identificadores de usuario, direcciones IP, rutas de petición y todo lo que a la aplicación le pareció bien registrar, y que esos datos vayan camino de un almacén analítico no convierte a un conversor web encontrado en un buscador en una parada aceptable del trayecto. Merece la pena recordar además que Parquet es binario y no editable: si el fichero va a una persona y no a un motor de consultas, una hoja de cálculo es mejor destino.
| NDJSON | Parquet | |
|---|---|---|
| Nombre completo | Newline-Delimited JSON | Apache Parquet |
| Extensión de archivo | .ndjson, .jsonl | .parquet |
| Tipo de medio | application/x-ndjson | application/vnd.apache.parquet |
| Compresión | — | Sin pérdida — no se descarta nada |
| Publicado por primera vez | 2013 | 2013 |
| Publicado por | — | Apache Software Foundation |
| 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 Parquet, así que puedes comparar el resultado con el original sin un segundo programa.
Parquet viene de Apache Software Foundation y es de 2013. pandas, Apache Spark y DuckDB lo leen.
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. El motor de este par concreto es parquet-wasm, una compilación en WebAssembly del lector de Apache Arrow; tu navegador lo descarga una vez y lo guarda.
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. parquet-wasm se descarga en tu equipo y se ejecuta allí, y por eso no hay contador.
NDJSON y Parquet 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 Apache Parquet.