FHIRPath Patch
The FHIR standard defines a FHIR-native mechanism for expressing changes to a FHIR resource in terms of only the delta you wish to apply. This syntax is called FHIRPath Patch (also often called FHIR Patch).
A FHIRPath Patch document is a Parameters resource with any number of patch operations (add an element, delete an element, etc.). Each operation in the document will be applied in order.
The HAPI FHIR FhirPatchBuilder class can be helpful as a way of generating FHIR Patch documents.
The Add operation takes a path to a parent element within a resource (or the name of the resource itself), the name of the element to add, and a value to actually add.
{
"resourceType": "Parameters",
"parameter": [ {
"name": "operation",
"part": [ {
"name": "type",
"valueString": "add"
}, {
"name": "path",
"valueString": "Patient"
}, {
"name": "name",
"valueString": "identifier"
}, {
"name": "value",
"valueIdentifier": {
"system": "http://system",
"value": "value-new"
}
} ]
} ]
}
FhirPatchBuilder builder = new FhirPatchBuilder(myContext);
builder
.add()
.path("Patient")
.name("identifier")
.value(new Identifier().setSystem("http://system").setValue("value-new"));
IBaseParameters patch = builder.build();
The Insert operation takes a path to a repeatable element, an index to insert at, and a value to actually insert.
{
"resourceType": "Parameters",
"parameter": [ {
"name": "operation",
"part": [ {
"name": "type",
"valueString": "insert"
}, {
"name": "path",
"valueString": "Patient.identifier"
}, {
"name": "index",
"valueInteger": 1
}, {
"name": "value",
"valueIdentifier": {
"system": "http://system",
"value": "value-new"
}
} ]
} ]
}
FhirPatchBuilder builder = new FhirPatchBuilder(myContext);
builder
.insert()
.path("Patient.identifier")
.index(1)
.value(new Identifier().setSystem("http://system").setValue("value-new"));
IBaseParameters patch = builder.build();
The Delete operation takes a path to an element to delete.
By default, the operation will fail if the path matches multiple elements, but this can be changed with the allowMultipleMatches
option as described in Deleting Multiple Elements below.
{
"resourceType": "Parameters",
"parameter": [ {
"name": "operation",
"part": [ {
"name": "type",
"valueString": "delete"
}, {
"name": "path",
"valueString": "Patient.identifier[1]"
} ]
} ]
}
FhirPatchBuilder builder = new FhirPatchBuilder(myContext);
builder
.delete()
.path("Patient.identifier[1]");
IBaseParameters patch = builder.build();
Per the FHIR Patch specification, the specified path must only match one element. This can be controlled by adding an additional parameter to the delete operation called allowMultipleMatches
with a boolean value of true
.
{
"resourceType": "Parameters",
"parameter": [ {
"name": "operation",
"part": [ {
"name": "type",
"valueString": "delete"
}, {
"name": "path",
"valueString": "Patient.identifier.where(system='http://system0')"
}, {
"name": "allowMultipleMatches",
"valueBoolean": true
} ]
} ]
}
FhirPatchBuilder builder = new FhirPatchBuilder(myContext);
builder
.delete()
.path("Patient.identifier.where(system='http://system0')")
.allowMultipleMatches();
IBaseParameters patch = builder.build();
The Replace operation takes a path to an element to replace, and a value to actually replace it with. The path must resolve to a single element.
{
"resourceType": "Parameters",
"parameter": [ {
"name": "operation",
"part": [ {
"name": "type",
"valueString": "replace"
}, {
"name": "path",
"valueString": "Patient.identifier[1]"
}, {
"name": "value",
"valueIdentifier": {
"system": "http://system",
"value": "value-new"
}
} ]
} ]
}
FhirPatchBuilder builder = new FhirPatchBuilder(myContext);
builder
.replace()
.path("Patient.identifier[1]")
.value(new Identifier().setSystem("http://system").setValue("value-new"));
IBaseParameters patch = builder.build();
The move operation takes a path to a repeatable element to move, and a source and destination index.
{
"resourceType": "Parameters",
"parameter": [ {
"name": "operation",
"part": [ {
"name": "type",
"valueString": "move"
}, {
"name": "path",
"valueString": "Patient.identifier"
}, {
"name": "source",
"valueInteger": 1
}, {
"name": "destination",
"valueInteger": 2
} ]
} ]
}
FhirPatchBuilder builder = new FhirPatchBuilder(myContext);
builder
.move()
.path("Patient.identifier")
.source(1)
.destination(2);
IBaseParameters patch = builder.build();
The following example shows a FHIR Patch which operated on an Observation resource. It removes any and all values in Observation.code.coding
with a Coding.system
value of 'http://loinc.prg', and adds a new LOINC code in their place.
This document should always leave exactly one LOINC code in Observation.code
regardless of whether there was previously no such code, one code, or multiple codes.
{
"resourceType": "Parameters",
"parameter": [ {
"name": "operation",
"part": [ {
"name": "type",
"valueString": "delete"
}, {
"name": "path",
"valueString": "Observation.code.coding.where(system='http://loinc.org')"
}, {
"name": "allowMultipleMatches",
"valueBoolean": true
} ]
}, {
"name": "operation",
"part": [ {
"name": "type",
"valueString": "add"
}, {
"name": "path",
"valueString": "Observation.code"
}, {
"name": "name",
"valueString": "coding"
}, {
"name": "value",
"valueCoding": {
"system": "http://loinc.org",
"code": "85354-9",
"display": "Blood Pressure"
}
} ]
} ]
}
To build this patch document in Java:
FhirPatchBuilder builder = new FhirPatchBuilder(myContext);
// Delete any existing LOINC codes
builder
.delete()
.path("Observation.code.coding.where(system='http://loinc.org')")
.allowMultipleMatches();
// Add a specific LOINC code
builder
.add()
.path("Observation.code")
.name("coding")
.value(new Coding("http://loinc.org", "85354-9", "Blood Pressure"));
IBaseParameters patch = builder.build();
You are about to leave the Smile Digital Health documentation and navigate to the Open Source HAPI-FHIR Documentation.