Skip to content

Migrate internal FHIR models to R4B#195

Merged
jenniferjiangkells merged 7 commits intomainfrom
feat/r4b-migration
Mar 30, 2026
Merged

Migrate internal FHIR models to R4B#195
jenniferjiangkells merged 7 commits intomainfrom
feat/r4b-migration

Conversation

@jenniferjiangkells
Copy link
Copy Markdown
Member

@jenniferjiangkells jenniferjiangkells commented Mar 30, 2026

Description

Problem

The fhir.resources library uses R5 as its default (top-level) import - every time you do from fhir.resources import Patient, you get the R5 model. However, in practice, FHIR R4 is the most widely adopted standard in production EHR systems by a significant margin. Deserializing real-world EHR responses with R5 models can cause two categories of failure:

  • Hard failures: Resources restructured or renamed in R5 fail to parse at all. MedicationStatement was renamed MedicationUsage; DeviceUseStatement was merged into DeviceUsage. Any R4 server returning these would error immediately.
  • Silent data loss: Fields renamed between versions are silently dropped. In R4, MedicationRequest has separate medicationCodeableConcept / medicationReference fields; R5 merged these into medication: CodeableReference. Deserializing an R4 response with an R5 model discards the medication data with no error raised.

Solution

Migrate all internal HealthChain models to R4B. fhir.resources provides R4B as its R4-compatible subpackage (fhir.resources.r4b) and treats it as the authoritative R4-era model - R4B is structurally equivalent to R4 for the overwhelming majority of resources, carrying forward R4 shapes with targeted corrections. HealthChain aligns with this decision so real-world EHR responses deserialize correctly by default.

The healthchain.fhir.r4b import surface

Rather than exposing fhir.resources.r4b directly to users, HealthChain re-exports FHIR types through healthchain.fhir.r4b:

  from healthchain.fhir.r4b import Patient, Condition, Observation                                                                                                                                                 

As a wrapper, HealthChain should own this import path. If the underlying fhir.resources library changes its packaging, version strategy, or module structure in a future release, only HealthChain's re-export layer needs to update - user code stays the same. It also keeps the API surface intentional: only types that HealthChain actively supports and tests against are surfaced here.

Version conversion

convert_resource(resource, "R5") remains available for interop with R5/STU3 systems. It serializes and re-deserializes the resource - best-effort, not lossless. Fields absent in the target version are dropped.

Changes

  • All internal imports migrated from fhir.resources (R5) to fhir.resources.R4B
  • healthchain.fhir.r4b added as the canonical public import surface for R4B resource classes
  • Resource helpers and element helpers simplified: direct R4B imports, no version dispatch
  • Bundle helpers updated for R4B compatibility
  • Interop engine updated to handle R4B bundles
  • Gateway clients updated to deserialize R4B resources correctly
  • All tests updated and passing

Breaking

  • version= removed from all create_* helpers
  • set_default_version / reset_default_version removed from healthchain.fhir - global state is messy to manage
  • bundle_to_dataframe observation columns renamed obs_{code}_{display} for consistency

@jenniferjiangkells jenniferjiangkells merged commit 9915d41 into main Mar 30, 2026
8 checks passed
@jenniferjiangkells jenniferjiangkells deleted the feat/r4b-migration branch March 30, 2026 17:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant