Skip to main content

Examples

This page is a curated set of different mapping examples.

Each example includes:

  • Input context (inline JSON)
  • Mapping snippet
  • Output fragment (only the relevant part)
  • A short explanation of the feature demonstrated

Example 1 — Basic assignments and nested context rules

Input:

{
"firstName": "Avery",
"lastName": "ExampleCare",
"dateOfBirth": "1985-01-23"
}

Mapping:

InstanceOf: Patient
* active = true
* birthDate = dateOfBirth

* name
* family = lastName
* given = [firstName]
* text = firstName & " " & lastName

Output fragment:

{
"resourceType": "Patient",
"active": true,
"birthDate": "1985-01-23",
"name": [
{
"family": "ExampleCare",
"given": ["Avery"],
"text": "Avery ExampleCare"
}
]
}

Explanation: The left-hand side paths decide the FHIR target element; the right-hand side expressions compute values from the input context. The * name block changes the FHIR target context for nested rules, not the input context.

Example 2 — Instance: sets id (and ordering matters)

Input:

{ "mrn": "EC-0001" }

Mapping:

Instance: "examplecare-patient-ec-0001"
InstanceOf: Patient
* identifier
* system = "urn:examplecare:mrn"
* value = mrn

Output fragment:

{
"resourceType": "Patient",
"id": "examplecare-patient-ec-0001",
"identifier": [
{ "system": "urn:examplecare:mrn", "value": "EC-0001" }
]
}

Explanation: Instance: is treated like an id write that runs before the rest of the rules. When you use Instance:, it appears first and is immediately followed by InstanceOf:.

Example 3 — Variables, comments, and trailing semicolons

Input:

{
"firstName": "Jordan",
"lastName": "ExampleCare"
}

Mapping:

InstanceOf: Patient
// ExampleCare demo mapping
$fullName := firstName & " " & lastName

* name.text = $fullName;
* active = true; /* trailing semicolons are allowed */

Output fragment:

{
"resourceType": "Patient",
"active": true,
"name": [
{ "text": "Jordan ExampleCare" }
]
}

Explanation: $var := ... binds a variable that later rules can reference. The comment lines annotate the mapping in place, and a trailing ; after a rule does not change behavior.

Example 4 — Input-context fan-out over an array

Input:

{
"phones": [
{ "value": "+1-555-0100" },
{ "value": "+1-555-0199" }
]
}

Mapping:

InstanceOf: Patient
* (phones).telecom
* system = "phone"
* value = value

Output fragment:

{
"telecom": [
{ "system": "phone", "value": "+1-555-0100" },
{ "system": "phone", "value": "+1-555-0199" }
]
}

Explanation: When the input-context expression produces an array, the nested rule set evaluates once per item. Inside the nested block, the input context is each phone object.

Example 5 — Fan-out with value + index bindings (@$v and #$i)

Input:

{
"phones": [
{ "value": "+1-555-0100" },
{ "value": "+1-555-0199" }
]
}

Mapping:

InstanceOf: Patient
* (phones@$p#$i).telecom
* system = "phone"
* value = $p.value
* rank = $i + 1

Output fragment:

{
"telecom": [
{ "system": "phone", "value": "+1-555-0100", "rank": 1 },
{ "system": "phone", "value": "+1-555-0199", "rank": 2 }
]
}

Explanation: The context expression can bind the current item (@$p) and the index (#$i). That gives you stable access to both the element and its position while building repeating output structures.

Example 6 — Append vs override (repeating element appends)

Input:

{
"legalFamily": "ExampleCare",
"legalGiven": "Avery",
"preferredGiven": "AJ"
}

Mapping:

InstanceOf: Patient
* name
* use = "official"
* family = legalFamily
* given = [legalGiven]

* name
* use = "usual"
* family = legalFamily
* given = [preferredGiven]

Output fragment:

{
"name": [
{ "use": "official", "family": "ExampleCare", "given": ["Avery"] },
{ "use": "usual", "family": "ExampleCare", "given": ["AJ"] }
]
}

Explanation: Patient.name repeats (maximum cardinality *), so each separate * name context block contributes a new array entry.

Example 7 — max=1 merge behavior (multiple writes combine)

Input:

{
"maritalText": "Married",
"maritalCode": "M"
}

Mapping:

InstanceOf: Patient
* maritalStatus.text = 'will be overwritten'
* maritalStatus.coding.code = maritalCode
* maritalStatus.text = maritalText

Output fragment:

{
"resourceType": "Patient",
"maritalStatus": {
"text": "Married",
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/v3-MaritalStatus",
"code": "M",
"display": "Married"
}
]
}
}

Explanation: maritalStatus is max=1, so separate contributions merge into a single object, and conflicts resolve as “later wins”.

Example 8 — Inline object assignment (complex types)

Input:

{
"city": "ExampleCare City",
"state": "MA",
"postal": "02110"
}

Mapping:

InstanceOf: Patient
* address = {
'city': city,
'state': state,
'postalCode': postal,
'country': 'US'
}

Output fragment:

{
"address": [
{
"city": "ExampleCare City",
"state": "MA",
"postalCode": "02110",
"country": "US"
}
]
}

Explanation: Assigning an object literal to a complex element writes that structure and validates it against the FHIR type. Because address repeats, assigning a single object creates a single array entry.

Example 9 — Array-of-objects assignment (and empty objects are dropped)

Input:

{
"addresses": [
{ "city": "ExampleCare City", "country": "US" },
{ "city": null, "country": null }
]
}

Mapping:

InstanceOf: Patient
* address = addresses.{
"city": city,
"country": country
}

Output fragment:

{
"address": [
{ "city": "ExampleCare City", "country": "US" }
]
}

Explanation: When you assign an array to a repeating complex element, each array item becomes an entry. Items that end up as empty objects (for example, all fields are null/undefined) are filtered out and do not produce output entries.

Example 10 — Choice types + Quantity shorthand (valueQuantity = 180)

Input:

{ "systolic": 130, "diastolic": 80 }

Mapping:

// Create an instance of a blood pressure profile
InstanceOf: http://hl7.org/fhir/StructureDefinition/bp
* status = "final"
* subject.display = first_name & ' ' & last_name
* effectiveDateTime = $now()
* component[SystolicBP].value = systolic
* component[DiastolicBP].value = diastolic

Output:

{
"resourceType": "Observation",
"meta": {
"profile": [
"http://hl7.org/fhir/StructureDefinition/bp"
]
},
"status": "final",
"category": [
{
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/observation-category",
"code": "vital-signs",
"display": "Vital Signs"
}
]
}
],
"code": {
"coding": [
{
"system": "http://loinc.org",
"code": "85354-9"
}
]
},
"subject": {
"display": "Avery Reed"
},
"effectiveDateTime": "2026-03-30T22:56:19.492Z",
"component": [
{
"code": {
"coding": [
{
"system": "http://loinc.org",
"code": "8480-6"
}
]
},
"valueQuantity": {
"value": 130,
"unit": "millimeter of mercury",
"system": "http://unitsofmeasure.org",
"code": "mm[Hg]"
}
},
{
"code": {
"coding": [
{
"system": "http://loinc.org",
"code": "8462-4"
}
]
},
"valueQuantity": {
"value": 80,
"unit": "millimeter of mercury",
"system": "http://unitsofmeasure.org",
"code": "mm[Hg]"
}
}
]
}

Explanation: For choice types like value[x] that have been profiled down to a single type like in the bood pressure profile components, you target the base name (like value). When the target is a Quantity, a primitive RHS can be assigned directly and it will be wrapped into a Quantity object by using the shorthand behavior. Profile derived fixed values like the category and code, systolic/diastolic component.code and the measuring unit in valueQuantity are injected.

Example 11 — Primitive child writes route to underscore siblings

Input:

{ "reason": "unknown" }

Mapping:

InstanceOf: Patient
* gender = "unknown"
* extension[data-absent-reason].value = "unknown"

Output fragment:

{
"resourceType": "Patient",
"gender": "unknown",
"_gender": {
"extension": [
{
"url": "http://hl7.org/fhir/StructureDefinition/data-absent-reason",
"valueCode": "unknown"
}
]
}
}

Explanation: gender is a primitive element, so child paths like gender.extension... write under the underscore sibling (_gender). The bracket selector targets an extension by a canonical identifier. The extension definition dictates the URL and type of value[x] (code in this case). Once it is narrowed down to a single type, the rule can target extension.value and the type is inferred, which means a valueCode JSON element will be created.

Example 12 — Repeating primitives keep underscore alignment

Input:

{
"line1": "100 Example St",
"line2": "Suite 200"
}

Mapping:

InstanceOf: Patient
* address
* line = line1
* line = line2
* extension[http://hl7.org/fhir/StructureDefinition/data-absent-reason]
* valueCode = "unknown"

Output fragment:

{
"address": [
{
"line": ["100 Example St", "Suite 200"],
"_line": [
null,
{
"extension": [
{
"url": "http://hl7.org/fhir/StructureDefinition/data-absent-reason",
"valueCode": "unknown"
}
]
}
]
}
]
}

Explanation: When a primitive repeats (like Address.line[]), per-item child properties (like extensions) appear under an underscore sibling array (_line[]) with index alignment. The null placeholder keeps _line[1] aligned with line[1].

Example 13 — Inline resources and Bundle composition (JSONata orchestration)

Input:

{
"patient": { "firstName": "Avery", "lastName": "ExampleCare" },
"encounter": { "status": "finished" }
}

Mapping:

(
$patientId := "examplecare-patient-001";

$patient := (
Instance: $patientId
InstanceOf: Patient
* active = true
* name.text = patient.firstName & " " & patient.lastName
);

$encounter := (
InstanceOf: Encounter
* status = encounter.status
* subject.reference = "Patient/" & $patientId
);

(
InstanceOf: Bundle
* type = "collection"

* entry
* resource = $patient

* entry
* resource = $encounter
)
)

Output fragment:

{
"resourceType": "Bundle",
"type": "collection",
"entry": [
{
"resource": {
"resourceType": "Patient",
"id": "examplecare-patient-001",
"active": true,
"name": [{ "text": "Avery ExampleCare" }]
}
},
{
"resource": {
"resourceType": "Encounter",
"status": "finished",
"subject": { "reference": "Patient/examplecare-patient-001" }
}
}
]
}

Explanation: JSONata orchestration of FLASH blocks builds multiple resources and then a final Bundle containing them. Resource-typed targets (like Bundle.entry.resource) expect an object with resourceType.

Example 14 — undefined is ignored, but false and 0 are preserved

Input:

{ "status": "inactive" }

Mapping:

InstanceOf: Patient
* active = status = 'active'
* deceasedBoolean = isDeceased // missing attribute

Output:

{
"resourceType": "Patient",
"active": false
}

Explanation: The expression status = "active" produces false, and false is a meaningful value that is written. The missing isDeceased field evaluates to undefined, so deceasedBoolean is not written at all.

Example 15 — Error example: missing resourceType when writing a Resource

Input:

{ "containedId": "examplecare-contained-1" }

Mapping:

InstanceOf: Patient
* contained = {
"id": containedId
}

Output fragment:

No output for this rule (evaluation produces a validation diagnostic).

Explanation: When you target a Resource-typed element (like contained), the assigned object is expected to be a FHIR resource. An object without a resourceType triggers a validation diagnostic; depending on your diagnostic thresholds it may throw, log, collect, or be inhibited.