Profiling and Validation

Last updated 2 months ago

Overview

FHIR resources are very loose in requirements which gives FHIR its flexibility. For example, all elements are optional in the Patient resource, and it's possible to create a Patient resource without any data which does not make much sense. So, sometimes there is a need to constraint resources. In FHIR, you need to create a StructureDefinition resource and describe the requirements for a resource you want to restrict. And it is definitely not an easy task. There are special tools developed specifically for this. And there is an alternative — custom profiling in Aidbox which is in fact a well-known JSON Schema.

Request
Response
POST /Patient
Status: 201
id: 6c2b9ea9-ea57-4f9a-9c9a-6c46cbad43da
resourceType: Patient
meta:
...

For custom profiling, Aidbox provides additional resource AidboxProfile. This resource specifies resource type and JSON Schema which will validate the specified resource type.

AidboxProfile Resource Structure

bind

The bind element is of type Reference. It specifies resource type which the profile will be applied to.

Example: Binding to Practitioner resource.

YAML
JSON
bind:
id: Practitioner # Target resource type "Practitoner"
resourceType: Entity
{
"bind": {
"id": "Practitioner",
"resourceType": "Entity"
}
}

schema

It's a plain JSON Schema object which will validate a resource.

Example: Require the name attribute

YAML
JSON
schema:
type: object
required:
- name
{
"schema": {
"type": "object",
"required": ["name"]
}
}

Examples

Require Properties

Let's validate newly created Patient resources by specifying that name and gender properties are required. First, we need to create the appropriate AidboxProfile resource.

Request YAML
Request JSON
Response
POST /AidboxProfile
resourceType: AidboxProfile
id: custom-patient-constraint
bind:
id: Patient
resourceType: Entity
schema:
type: object
required:
- name
- gender
POST [base]/AidboxProfile
{
"resourceType": "AidboxProfile",
"id": "custom-patient-constraint",
"bind": {
"id": "Patient",
"resourceType": "Entity"
},
"schema": {
"type": "object",
"required": [
"name",
"gender"
]
}
}
STATUS: 201
{
"bind": {
"id": "Patient",
"resourceType": "Entity"
},
"schema": {
"required": [
"name",
"gender"
]
},
"id": "custom-patient-constraint",
"resourceType": "AidboxProfile",
"meta": {
"lastUpdated": "2018-10-10T14:45:43.801Z",
"versionId": "2",
"tag": [{
"system": "https://aidbox.io",
"code": "created"
}
]
}
}

If you are using Aidbox.Dev below 0.3.1 version, then after creating an AidboxProfile resource you will need to restart your Aidbox.Dev server.

$ docker-compose down && docker-compose up -d

Now, let's try to create a Patient resource without name and/or gender . You will receive the error.

Request YAML
Request JSON
Response
POST /Patient
resourceType: Patient
birthDate: '1985-01-11'
POST [base]/Patient
{
"resourceType": "Patient",
"birthDate": "1985-01-11"
}
STATUS: 422
{
"resourceType": "OperationOutcome",
"errors": [{
"path": [],
"message": "Property name is required",
"profile": {
"id": "custom-patient-constraint",
"resourceType": "AidboxProfile"
}
}, {
"path": [],
"message": "Property gender is required",
"profile": {
"id": "custom-patient-constraint",
"resourceType": "AidboxProfile"
}
}
],
"warnings": []
}

Require Nested Properties

Let's require given and family elements of the name property. In this case, we are expecting that name attribute of the type HumanName will contain elements given and family. Let's create the AidboxProfile resource with the code below. Then you will need to restart server if you're on Aidbox.Dev.

Request YAML
Request JSON
Response
POST /AidboxProfile
resourceType: AidboxProfile
id: custom-patient-constraint
bind:
id: Patient
resourceType: Entity
schema:
type: object
required:
- name
properties:
name:
type: array
minItems: 1
items:
type: object
required:
- given
- family
properties:
given:
type: array
minItems: 1
items:
type: string
family:
type: string
POST [base]/AidboxProfile
{
"resourceType": "AidboxProfile",
"id": "custom-patient-constraint",
"bind": {
"id": "Patient",
"resourceType": "Entity"
},
"schema": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": [
"given",
"family"
],
"properties": {
"given": {
"type": "array",
"minItems": 1,
"items": {
"type": "string"
}
},
"family": {
"type": "string"
}
}
}
}
}
}
}
STATUS: 201
{
"bind": {
"id": "Patient",
"resourceType": "Entity"
},
"schema": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "array",
"items": {
"type": "object",
"required": [
"given",
"family"
],
"properties": {
"given": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 1
},
"family": {
"type": "string"
}
}
},
"minItems": 1
}
}
},
"id": "custom-patient-constraint",
"resourceType": "AidboxProfile",
"meta": {
"lastUpdated": "2018-10-11T09:47:18.147Z",
"versionId": "12",
"tag": [{
"system": "https://aidbox.io",
"code": "created"
}
]
}
}

Now, on Patient resource creation we will be receiving the validation error. Let's try to create a Patient resource without a family name. You will receive the error.

Request YAML
Request JSON
Response
POST /Patient
name:
- text: John Malcovich
given:
- John
POST [base]/Patient
{
"name": [
{
"text": "John Malcovich",
"given": [
"John"
]
}
]
}
STATUS: 422
{
"resourceType": "OperationOutcome",
"errors": [
{
"path": [
"name",
0
],
"message": "Property family is required",
"profile": {
"id": "custom-patient-constraint",
"resourceType": "AidboxProfile"
}
}
],
"warnings": []
}