Cómo Abrir una Exportación NDJSON de FHIR
Hl7 Tools

Cómo Abrir una Exportación NDJSON de FHIR

Pediste una Exportación y Recibiste un Fichero .ndjson

Una exportación masiva aterriza en tu bandeja o en tu almacenamiento de objetos y, en lugar de un documento JSON ordenado, tienes varios ficheros con extensión .ndjson, algunos de cientos de megabytes. Haces doble clic en uno y tu editor se niega, se cuelga, o abre una única línea de texto que se extiende durante un kilómetro. Nada de la experiencia sugiere que estés ante datos bien formados, pero lo están. NDJSON es exactamente el formato correcto para lo que hace una exportación masiva; simplemente es poco cooperativo con las herramientas de todos los días.

Esta guía explica qué es NDJSON, por qué los editores sufren con él, cómo recuperarte cuando una línea está rota y cómo trabajar los ficheros por tipo de recurso que produce realmente una exportación. Todo se puede hacer en el navegador con el Explorador de Bundles FHIR, que detecta NDJSON automáticamente y lo lee sin subir nada. Para el panorama general de cómo y por qué se solicita una exportación, La Exportación Bulk Data de FHIR Explicada cubre el flujo completo.

Qué Es NDJSON Exactamente

NDJSON —JSON delimitado por saltos de línea— es un formato contenedor con una sola regla: cada línea es un valor JSON completo e independiente, y las líneas van separadas por un salto de línea. Esa es toda la especificación. No hay array envolvente, ni comas entre registros, ni corchete de cierre al final. Un fichero NDJSON de diez millones de registros y otro de uno solo tienen la misma estructura; el segundo es simplemente más corto.

La consecuencia crítica es que el fichero completo no es JSON válido. Si lo pegas en un validador JSON falla de inmediato, porque tras la primera llave de cierre encuentra otra de apertura donde JSON espera el fin del documento. Esto desconcierta a casi todo el mundo la primera vez. El fichero no está corrupto: lo estás validando con la gramática equivocada. Cada línea es JSON válido. El fichero es una secuencia de ellas.

La guía de implementación FHIR Bulk Data Access, publicada por HL7 en hl7.org/fhir/uv/bulkdata/, especifica NDJSON como formato de salida de los recursos exportados. El motivo es el streaming: el productor puede escribir registros de uno en uno y volcarlos, y el consumidor puede procesarlos de uno en uno sin sostener nunca el conjunto entero en memoria. Con un array JSON envolvente ninguna de las dos partes puede empezar hasta que la otra termine, y el consumidor debe analizar el documento completo antes de ver el primer registro. Para un conjunto que cubre toda la población de pacientes de un hospital, esa diferencia es la que separa lo viable de lo inviable.

NDJSON No Es un Bundle

Merece la pena ser preciso con esta distinción, porque se confunden a menudo. Un Bundle es un recurso FHIR de pleno derecho —resourceType: "Bundle", con un type, metadatos opcionales y un array entry cuyos miembros envuelven los recursos reales y pueden llevar un fullUrl. NDJSON no tiene nada de eso. Es una secuencia desnuda de recursos, sin envoltorio, sin metadatos de bundle y sin fullUrl por entrada. Si dudas de qué tienes delante, mira el primer carácter de la segunda línea: un Bundle es un único documento JSON, así que su segunda línea es contenido indentado, mientras que la segunda línea de un NDJSON abre una { nueva en la columna uno. Qué Es un Bundle FHIR detalla la estructura del Bundle si necesitas la comparación.

Por Qué Sufre un Editor de Texto

Cuando abres una exportación masiva en un editor genérico se acumulan tres problemas distintos.

Longitud de línea. Un recurso FHIR serializado sin formatear es una línea larguísima —habitualmente de varios kilobytes, y mucho más si lleva una narrativa text grande o un array contained extenso. Los editores se construyen sobre la suposición de que las líneas son cortas: el resaltado de sintaxis, el emparejamiento de llaves y el ajuste de línea tienen coste por carácter dentro de una línea. Un fichero de diez mil líneas de varios kilobytes cae en ese caso patológico diez mil veces.

Tamaño del fichero. Muchos editores cargan el fichero entero en memoria y construyen un índice sobre él. Una exportación de 400 MB se convierte en varios gigabytes de estado del editor. En un portátil eso significa swap, después una rueda girando y después un cierre forzado.

Las herramientas de formateo lo empeoran. El impulso es recurrir a "Formatear documento" o a un embellecedor de JSON para hacer legible el muro de texto. Eso falla por lo dicho antes —el fichero no es JSON válido— y el mensaje de error suele ser una queja poco útil sobre un token inesperado en un desplazamiento gigantesco, que se lee como corrupción y no como un desajuste de gramática.

Lo que quieres es un lector que trate el fichero como el formato pretende: línea a línea, analizando cada registro por separado y guardando solo lo necesario para mostrarlo. Eso es lo que hace un visor NDJSON específico, y por eso el mismo fichero que atasca un editor se abre rápido en él.

Cómo Abrir una Exportación NDJSON de FHIR

Qué Hacer con una Línea Rota

Como los registros son independientes, NDJSON se degrada mucho mejor que JSON, pero solo si tu lector está preparado para aprovecharlo. En un documento JSON único, un carácter mal puesto invalida todo; no existe el análisis parcial. En NDJSON, una línea malformada es un registro malo entre miles de buenos.

Las líneas corruptas no son una rareza. Una transferencia interrumpida a mitad de escritura deja una última línea truncada. Un fichero montado concatenando trozos puede acabar con un salto de línea ausente donde chocaron dos registros. Un script bienintencionado que filtró el fichero con la herramienta equivocada puede dejar un fragmento suelto. En todos los casos el comportamiento correcto es el mismo: informar de la línea mala y conservar el resto.

El Explorador hace exactamente eso. El análisis nunca lanza una excepción ante contenido malo: los problemas se convierten en incidencias reportadas en lugar de en un fallo total, así que una sola línea ilegible no puede descartar las otras diecinueve mil buenas. Se reportan dos problemas distintos por separado, y la diferencia importa para el diagnóstico. "La línea no es JSON válido" significa que no se pudo analizar en absoluto, normalmente por truncamiento o por un límite de trozo roto. "La línea es JSON pero no es un recurso FHIR (sin resourceType)" significa que la línea se analizó bien pero no es un recurso; es lo que ves cuando un manifiesto, una entrada de log o un OperationOutcome se han concatenado al mismo fichero. Cada incidencia lleva su número de línea en base 1, así que puedes ir a esa línea en tu editor y mirarla aislada en lugar de buscar a ciegas.

De ahí salen dos hábitos prácticos. Primero, contrasta siempre el número de incidencias con el de recursos antes de sacar conclusiones de los datos: un fichero que analizó 4.812 recursos con 3 errores se puede explorar, pero no se puede conciliar con el sistema origen hasta saber qué eran esos tres. Segundo, si la única línea mala es la última, sospecha de una descarga truncada y vuelve a bajarte el fichero antes de invertir tiempo en el contenido.

Ficheros por Tipo de Recurso, y Por Qué Ayuda

Una exportación masiva no te entrega un único fichero enorme. La guía Bulk Data Access hace que el servidor produzca un conjunto de ficheros, cada uno con recursos de un solo tipo; el manifiesto de finalización los lista con su type y una url de descarga. Así que una exportación típica es un directorio con Patient, Observation, Condition, Encounter, MedicationRequest: uno o varios ficheros de cada. Los tipos grandes se reparten a menudo en varios ficheros, así que ver tres ficheros de Observation es normal y no significa que algo haya fallado.

Esto ayuda de verdad en lugar de estorbar, por dos motivos. Encaja con cómo quieres analizar los datos: cada fichero ya tiene un único esquema, así que se corresponde directamente con una tabla y un juego de columnas. Y te da una unidad de trabajo natural. En vez de pelearte con un monolito de 2 GB, abres el fichero de Patient para revisar la cohorte y luego el de Observation para revisar las mediciones. Si un fichero sigue siendo demasiado grande para un lector en navegador, la división sensata es por número de líneas: como cada línea es independiente, cortar un NDJSON por cualquier salto de línea produce dos NDJSON válidos, algo que no ocurre con ningún otro contenedor JSON.

Sobre los límites: el Explorador acepta entradas de hasta 25 MB y analiza hasta 20.000 recursos. Alcanzar cualquiera de los dos no es un evento silencioso: obtienes un recuento explícito de cuántos recursos se descartaron, así que siempre sabes si la tabla que tienes delante es el fichero entero o un prefijo. Esa honestidad importa más que un límite más alto, porque el fallo que no te puedes permitir es un conjunto truncado que creías completo.

Leer la Exportación Una Vez Abierta

Con el fichero analizado, la primera vista útil es el recuento por tipo de recurso: cuántos de cada uno has recibido realmente. Incluso en una exportación por tipo merece la pena comprobarlo, porque detecta al instante una descarga truncada o un fichero que resultó contener algo distinto de lo que su nombre prometía. A partir de ahí, el mismo flujo de tabla y CSV aplica a NDJSON igual que a un Bundle: eliges el tipo de recurso, tomas las columnas del preset o eliges las tuyas, y exportas. La mecánica de ese paso —unir frente a expandir, elección de columnas y las trampas de importación en Excel— está en Cómo Convertir un Bundle FHIR a CSV Sin Perder Datos.

Las referencias se comportan distinto en NDJSON que en un Bundle, y esto pilla a mucha gente. Las entradas de un Bundle pueden llevar fullUrl, que es lo que hace resolubles las referencias urn:uuid: dentro del documento. NDJSON no tiene envoltorio y por tanto no tiene fullUrl, así que los recursos solo son direccionables por su resourceType/id. En una exportación por tipo, eso significa que el subject.reference de una Observation apuntando a Patient/123 no resolverá mientras mires solo el fichero de Observations: el Patient vive en otro fichero. Es lo esperado, no un defecto de los datos. Cómo Funcionan las Referencias en FHIR explica las formas de referencia y cuándo la resolución es legítimamente imposible.

Que el Fichero No Salga de Tu Máquina

Una exportación masiva es, por definición, un gran volumen de información sanitaria protegida, a menudo el historial clínico de toda una población de pacientes. Subirla a un visor de JSON online genérico para ver qué contiene es una comunicación de datos, y muy difícil de justificar a posteriori. El análisis local en el navegador elimina la cuestión: el fichero lo lee JavaScript en tu pestaña, no se transmite nada, y puedes verificarlo en el panel de red. El mismo razonamiento se aplica a la resolución de referencias que hace el Explorador: resuelve únicamente dentro de los datos que has cargado y nunca pide un recurso referenciado a un servidor externo, porque hacerlo revelaría los identificadores que se le pidió consultar.

Conclusión

NDJSON es un valor JSON completo por línea, nada más, y por eso el fichero entero nunca valida como JSON y por eso tu editor se atraganta. Léelo con algo que analice línea a línea: obtienes el recuento de recursos, una tabla real y números de línea precisos para cada registro que falló, en lugar de un error de todo o nada. Trata los ficheros por tipo como la unidad natural de trabajo, parte los grandes por cualquier salto de línea y confirma el recuento de incidencias antes de fiarte de una conciliación. Abre tu próxima exportación en el Explorador de Bundles FHIR y el fichero se quedará en tu máquina mientras lo haces.

← Volver al Blog