HL7v2 to FHIR - Z-segments and extensions
Preserve custom Z-segment data instead of dropping it - each segment becomes a Basic resource with extensions holding every populated field.
Z-segments are the custom, site-defined segments of HL7v2 - ZPD, ZIN, ZBE and the other segments vendors define for data the standard does not cover. FHIR has no resource for them, so the conversion preserves each one as a Basic resource whose extensions hold every populated field.
What a Z-segment becomes
from zato.hl7v2 import parse_hl7
raw = (
'MSH|^~\\&|SENDER|FACILITY|RECEIVER|FAC|20260315101112||ADT^A01^ADT_A01|CTL001|P|2.9\r'
'PID|||12345^^^HOSP^MR||SMITH^JOHN^A||19800115|M\r'
# A custom segment with a membership level and a renewal year
'ZPD|GOLD|2026\r'
)
msg = parse_hl7(raw, validate=False)
bundle = msg.to_fhir()
print(msg.to_fhir_json(indent=2))
The ZPD segment produces this entry in the bundle:
{
"resourceType": "Basic",
"code": {
"coding": [
{
"system": "urn:zato:hl7v2:extension/segment",
"code": "ZPD"
}
]
},
"extension": [
{
"url": "urn:zato:hl7v2:extension/ZPD/1",
"valueString": "GOLD"
},
{
"url": "urn:zato:hl7v2:extension/ZPD/2",
"valueString": "2026"
}
],
"subject": {
"reference": "urn:uuid:98e4f8aa-a5ad-5791-add1-66fd3afb4f83"
}
}
In this entry:
- The resource's
codenames the segment the data comes from -ZPD - Each populated field becomes one extension whose URL ends with the segment name and the field's position -
.../ZPD/1is ZPD-1,.../ZPD/2is ZPD-2 - Field values keep their HL7 wire form, so components stay separated with
^, repetitions with~and subcomponents with& subjectpoints at the Patient from the same bundle, so the custom data stays attached to the person it describes
A message may include any number of Z-segments and each becomes its own Basic resource, while a Z-segment with no populated fields produces nothing.
Standard segments that become Basic too
Two kinds of standard segments take the same route as a Z-segment. One is a segment without a mapping of its own, e.g. a UAC or a DSC, which has nothing else to become. The other is a segment that only enriches another resource and arrives without it - a PV2 in a message with no PV1, an RXR with no pharmacy segment before it, an AIS with no SCH. Rather than dropping the data, the conversion preserves the segment whole, with code naming the segment and one extension per field, exactly as above.
Two Z-segments have mappings of their own and do not become Basic resources when their parent is present - ZBE, the IHE PAM movement segment, enriches the Encounter, and ZDS, the quasi-standard imaging segment, adds the study instance UID to the ServiceRequest.
Setting the extension base URL
The default URLs are built under urn:zato:hl7v2:extension. To publish extensions under your own namespace, set base_url in the [extensions] section of the configuration file:
With this file, the ZPD-1 extension URL becomes http://example.org/fhir/ext/ZPD/1 and the segment code system http://example.org/fhir/ext/segment.
Unmapped fields of standard segments
A populated field of a standard segment that has no FHIR equivalent is preserved too - not as its own Basic resource, but as an extension on the resource built from its segment. A county code in PID-12 appears on the Patient as:
The unmapped URLs are built under the same base URL, so the [extensions] setting above changes them as well. Unknown code values are preserved the same way.
See also
| Page | What it covers |
|---|---|
| Customizing code mappings | Unknown code values, preserved as extensions the same way |
| Configuration | The extensions section that changes the base URL |
| What you get per message | Every segment-to-resource mapping, standard and custom alike |
Learn more
Schedule a meaningful demo
Book a demo with an expert who will help you build meaningful systems that match your ambitions
"We evaluated 12 integration platforms and Zato was the only one to score 100%."
Philip Zuñiga, Assistant Professor, University of the Philippines