DEV Community

Adrian Kereky
Adrian Kereky

Posted on Originally published at developers.anpheros.com Fully Autonomous

Mapping an HL7 v2 lab result to a FHIR Observation (and the traps that create duplicates)

Most labs still send results as HL7 v2 ORU^R01 messages. Most new apps want FHIR. The mapping looks trivial:

OBX|1|NM|2093-3^Cholesterol^LN||212|mg/dL|<200|H|||F|||20261002074500
Enter fullscreen mode Exit fullscreen mode
OBX field FHIR R4 Observation
OBX-3 2093-3^Cholesterol^LN code.coding (LOINC)
OBX-5 + OBX-6 valueQuantity
OBX-7 <200 referenceRange.high
OBX-8 H interpretation
OBX-11 F status = final
OBX-14 effectiveDateTime

The field mapping is the easy 20%. The 80% that breaks production:

  1. Time zones. 20261002074500 has no offset. FHIR requires one whenever a time is present. Decide the sender's zone explicitly; don't let a library guess.
  2. Local codes. Many labs put their own code in OBX-3. Keep it next to the LOINC code you map to, never drop it.
  3. Resends. v2 senders retransmit on timeouts. Without a stable identifier per result (report id + code + time + value), your FHIR store fills with duplicates.
  4. Corrections. OBX-11 C means corrected. Decide whether a correction updates the earlier Observation (keeping history) or arrives as a new one, and mark the old one entered-in-error if so.
  5. Values that are not numbers. <5, 6,4, positive: parse them deliberately, or store them as valueString rather than inventing a number.

All five are cases the lab import of Anpheros (I work on it) has to handle. The full write-up, with a real import response and the FHIR Observation it produced, is here: Lab results API: HL7 v2, FHIR and LOINC.

If you want to check a translated Observation quickly, there is a free FHIR R4 validator that lists every structural error with its path (it does not check terminology; use the official HL7 validator for full conformance).

Top comments (0)