Artículo
· 23 oct, 2025 Lectura de 10 min

La nueva validación basada en perfiles de servidor FHIR

Una novedad que apareció en la versión 2024.1 de InterSystems IRIS for Health y que quizá te pasó desapercibida. Se trata de la capacidad de realizar una validación basada en perfiles FHIR.

 

En este artículo os ofreceré una visión general básica de esta funcionalidad.

Si FHIR es importante para vosotros, deberíais probar sin duda esta nueva característica, así que seguid leyendo.

 

Contexto

El estándar FHIR define una operación llamada $validate. Esta operación está pensada para ofrecer una API que permita validar recursos.

Para entender mejor la validación FHIR en general, podéis consultar esta documentación de FHIR.

También podéis ver la sesión del Global Summit 2023, “Realización de validaciones FHIR avanzadas”, en la que en la primera parte se explican los distintos tipos de validaciones.

Parte de esta validación consiste en comprobar los recursos frente a perfiles específicos. Podéis ver más sobre esto en el apartado de Profiling.

Para ilustrarlo con un ejemplo sencillo, la definición base de FHIR para el recurso Patient establece que la cardinalidad del campo identifier es “0..”, lo que significa que un paciente podría no tener ningún identificador (cero) y seguir siendo válido. Sin embargo, el perfil US Core Patient define una cardinalidad de “1..”, lo que implica que un paciente sin identificador no sería válido.

Otros ejemplos, siguiendo el modelo del US Core Patient anterior, serían el uso de extensiones como race o birthsex.

Si queréis aprender más sobre el FHIR Profiling, podéis echar un vistazo a una sesión del Global Summit 2022 presentada por @Patrick Jamieson, “Using FHIR Shorthand”, en la que Pat explica el uso de FSH (FHIR Shorthand), pero comienza abordando el tema general del Profiling.

En versiones anteriores, nuestro servidor FHIR no admitía este tipo de validación —la validación basada en perfiles—, pero desde la versión 2023.3 ya está disponible.

Uso

Nuestra documentación incluye una sección sobre cómo llamar a $validate para realizar una validación basada en perfiles.

Hay dos formas básicas de llamar a la operación $validate.

Perfil en la URL de la consulta
Una de ellas consiste en enviar una petición POST con el recurso en el cuerpo de la solicitud y el perfil como un parámetro en la URL.

Por ejemplo, en Postman:

O usando curl (tened en cuenta la codificación de las barras en el valor del parámetro de la URL del perfil; Postman se encarga de eso por vosotros):

 curl --location 'http://fhirserver/endpoint/Patient/$validate?profile=http%3A%2F%2Fhl7.org%2Ffhir%2Fus%2Fcore%2FStructureDefinition%2Fus-core-patient%7C3.1.0' --header 'Content-Type: application/fhir+json' --header 'Accept: application/fhir+json' --header 'Authorization: Basic U3VwZXJVc2VyOnN5cw==' --data "@data.json"

Mientras que el archivo data.json mencionado arriba incluye, por ejemplo, este paciente válido del US Core:

 
Recurso de paciente en JSON

La respuesta de esta operación es un recurso OperationOutcome.

Si el recurso es válido (como se indicó anteriormente), deberíais esperar obtener este tipo de respuesta:

{
    "resourceType": "OperationOutcome",
    "issue": [
        {
            "severity": "information",
            "code": "informational",
            "details": {
                "text": "All OK"
            }
        }
    ]
}

Pero si, por ejemplo, omito los identificadores del recurso anterior, obtendré este OperationOutcome:

{
    "resourceType": "OperationOutcome",
    "issue": [
        {
            "severity": "error",
            "code": "invariant",
            "details": {
                "text": "generated-us-core-patient-1: Constraint violation: identifier.count() >= 1 and identifier.all(system.exists() and value.exists())"
            },
            "diagnostics": "Caused by: [[expression: identifier.count() >= 1, result: false, location: Patient]]",
            "expression": [
                "Patient"
            ]
        }
    ]
}

 

Perfil en el cuerpo de la consulta
La otra forma de enviar los datos a $validate es mediante un POST con el recurso dentro de un array de parámetros, junto con el perfil y otras opciones.

En Postman esto se verá así:

Con curl:

curl --location 'http://fhirserver/endpoint/Patient/$validate' --header 'Content-Type: application/fhir+json' --header 'Accept: application/fhir+json' --header 'Authorization: Basic U3VwZXJVc2VyOnN5cw==' --data "@data.json"

Tened en cuenta que la URL no incluye un perfil, pero ahora el contenido del cuerpo (o data.json en el ejemplo anterior) tiene este aspecto:

{
    "resourceType": "Parameters",
    "parameter": [
        {
            "name": "mode",
            "valueString": "profile"
        },
        {
            "name": "profile",
            "valueUri": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient|3.1.0"
        },
        {
            "name": "resource",
            "resource": {
                "resourceType": "Patient"
            }
        }
    ]
}

He excluido el recurso de paciente real, ya que es el mismo que en los ejemplos anteriores.

Pero lo que es diferente aquí es el elemento del parámetro mode, el del perfil, y que el recurso viene dentro de su propio elemento de parámetro, simplemente llamado “resource”.

Consultad la documentación mencionada anteriormente para ver más opciones de mode, incluyendo los casos en los que se puede incluir un ID en la URL (para validar, por ejemplo, una actualización o eliminación).

Para vuestra comodidad, he creado un paquete simple de Open Exchange que incluye una colección de Postman con solicitudes de ejemplo como las anteriores.

Posibles errores

Si omitís una versión para el perfil en el formato<profile URI>|<version number>, obtendréis un error <HSFHIRErr>ProfileVersionRequired  

Recibiríais un código de estado 400 y este tipo de OperationOutcome:

{
    "resourceType": "OperationOutcome",
    "issue": [
        {
            "severity": "error",
            "code": "invalid",
            "diagnostics": "<HSFHIRErr>ProfileVersionRequired",
            "details": {
                "text": "Profile URI 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient' does not include a version number.  Version number is required for profile validation."
            }
        }
    ]
}

Si proporcionáis un número de versión que no existe en el endpoint FHIR, obtendréis un error de tipo not-supported (esta vez el estado HTTP será 200).

Vuestro OperationOutcome tendrá, por ejemplo, este aspecto:

{
    "resourceType": "OperationOutcome",
    "issue": [
        {
            "severity": "error",
            "code": "not-supported",
            "details": {
                "text": "Profile 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient|15' is not supported"
            },
            "expression": [
                "Patient"
            ]
        }
    ]
}

Via Código

Tened en cuenta que, como alternativa a llamar a la operación $validate mediante la API REST estándar, internamente, si el caso de uso lo permite, también podéis llamar a un método de clase.

De forma similar al método que ya existía HS.FHIRServer.Util.ResourceValidator:ValidateResource() (mencionado también en la documentación), ahora existe un nuevo método llamado ValidateAgainstProfile() que podéis utilizar.

Alcance

Es importante tener en cuenta que actualmente (versión 2024.1) este tipo de validación (basada en perfiles) solo se realiza como parte de la operación $validate, pero no cuando se crean o actualizan recursos. En esos casos se realiza una validación más “básica”. Por tanto, si lo deseáis, podéis ejecutar vuestros recursos a través de la validación más “avanzada” basada en perfiles antes de hacer un POST o PUT.

Otras opciones podrían estar disponibles en versiones futuras.

 

Notas de configuración

En general, la buena noticia es que el servidor FHIR se encargará de la mayor parte de la configuración del validador de perfiles por vosotros.

Lo que sí debéis aseguraros es de tener un JDK de Java 11 compatible (actualmente el de Oracle o el de OpenJDK).

Podéis encontrar más detalles en la documentación de configuración del servidor de validación de perfiles.

Básicamente, lo que ocurre en segundo plano es que nos aseguramos de que haya un servidor de lenguaje externo (Java) en ejecución, para poder ejecutar el archivo JAR del validador (ubicado en la carpeta de instalación, bajo dev/fhir/java). Por cierto, si echáis un vistazo a la carpeta de registros y veis algunas advertencias, como:

CodeSystem-account-status.json : Expected: JsonArray but found: OBJECT for element: identifier

no os preocupéis, es normal. El validador carga muchos perfiles por defecto y algunos de ellos tienen pequeños errores de formato).

Así que, si revisáis vuestra lista de servidores de lenguaje externo, deberíais ver algo como esto:

Tened en cuenta que, cuando el validador necesita validar por primera vez contra un perfil, debe cargarlos, por lo que para mejorar el rendimiento podéis llamar al método HS.FHIRServer.Installer:InitalizeProfileValidator():

set status = ##class(HS.FHIRServer.Installer).InitializeProfileValidator(.error)

Esto también se menciona en la documentación antes citada sobre la configuración del validador.

De hecho, podríais incluir esta llamada en la rutina de inicio %ZSTART de vuestra instancia.

Y esto también se menciona en la referencia de clases relacionada:

Se recomienda llamar a este método después de reiniciar la instancia o el servidor de lenguaje externo, para evitar la pérdida de rendimiento que supondría cargar los perfiles durante la operación de validación.

 

Próximamente...

En las próximas versiones planeamos ofrecer más funcionalidades dentro y alrededor del validador.

Pero, por ejemplo, incluso hoy, si queréis realizar una validación basada en un servidor de terminología externo (como para los códigos LOINC), podéis usar un enfoque diferente, uno explicado y demostrado en la sesión del Global Summit mencionada anteriormente, basado en el ejemplo de mi compañero @Dmitry Zasypkin (disponible en Open Exchange).

 

Agradecimientos especiales

Gracias a @Kimberly Dunn, quien fue una fuente inestimable de información durante el análisis de esta nueva función y la preparación de este artículo.

(*) Gracias a Microsoft Bing y su Image Creator impulsado por DALL-E 3, que creó la imagen de arriba para mí.

Comentarios (0)1
Inicie sesión o regístrese para continuar