FHIR (Fast Healthcare Interoperability Resources) has revolutionized how healthcare data is exchanged between systems. Over the last decade, it has evolved from a nascent standard into the global language of health informatics.
The power of FHIR lies in its Resource-Based Model, which breaks down complex medical records into modular, reusable building blocks like Patient, Observation, and Medication. By leveraging a RESTful API architecture and modern data formats like JSON, FHIR ensures that health data is not just portable, but developer-friendly.
However, to truly master FHIR, you must understand the "DNA" of these resources: Data Types.
The 5 Categories of FHIR Data Types
Every resource is a collection of elements, and every element is defined by a data type. These are categorized into five distinct layers:
| Category | Description | Examples |
|---|---|---|
| 1. Base Types | The abstract foundation. Every FHIR type inherits from the Base class. |
Base, Element
|
| 2. Primitive Types | Single elements representing a single value (strings, numbers, dates). |
boolean, string, dateTime
|
| 3. General Purpose | Complex, reusable clusters representing common healthcare concepts. |
HumanName, Address, Quantity
|
| 4. Metadata Types | Types used to define "data about the data" for searching and cataloging. |
ContactDetail, UsageContext
|
| 5. Special Purpose | Specialized structures for specific technical usage within the spec. |
Reference, Extension, Narrative
|
Why Data Types Matter
Understanding these types is critical because FHIR is strictly typed. If a system expects a Quantity (which includes a value and a unit) and you send a simple integer, the exchange will fail. By mastering these categories, you ensure that your healthcare applications are not only interoperable but also robust and compliant with global standards.
Case Study: The Patient Resource
Let's look at a sample Patient resource to see these types in action.
{
"resourceType": "Patient",
"id": "example-patient-001",
"meta": {
"versionId": "1",
"lastUpdated": "2024-12-16T10:30:00Z",
"profile": ["http://hl7.org/fhir/StructureDefinition/Patient"]
},
"text": {
"status": "generated",
"div": "<div xmlns=\"http://www.w3.org/1999/xhtml\">John Doe, Male, DOB: 1990-05-15</div>"
},
"extension": [
{
"url": "http://hl7.org/fhir/StructureDefinition/patient-birthPlace",
"valueAddress": {
"city": "Lagos",
"country": "Nigeria"
}
}
],
"identifier": [
{
"use": "official",
"system": "http://hospital.example.org/patients",
"value": "MRN-123456"
}
],
"active": true,
"name": [
{
"use": "official",
"family": "Doe",
"given": ["John", "Michael"]
}
],
"gender": "male",
"birthDate": "1990-05-15",
"_birthDate": {
"extension": [
{
"url": "http://hl7.org/fhir/StructureDefinition/patient-birthTime",
"valueDateTime": "1990-05-15T14:30:00+01:00"
}
]
}
}
Let's Dive into the Data Types
1. Primitive Types (Simple Values)
- String: A sequence of Unicode characters (Max 1MB).
-
Boolean: Strict
trueorfalse. -
Code: A string from a controlled vocabulary (e.g.,
gender: "male"). -
DateTime vs. Instant: *
DateTime: For human events (can be partial, like just a year).-
Instant: A precise UTC timestamp for system events (e.g.,lastUpdated).
-
- Uri/Url/Canonical: Used for naming systems, external links, and referencing other profiles.
2. Complex Types (Composite Structures)
-
Identifier: Used for MRNs, SSNs, or Driver’s Licenses. It pairs a
system(the namespace) with avalue. - HumanName: Handles the complexity of global naming (prefixes, suffixes, multiple given names).
- CodeableConcept: The powerhouse of FHIR. It allows you to send a code from a system (like LOINC or SNOMED) along with the original text description.
-
Period: A simple range with a
startand an optionalend.
3. Special Purpose Types
-
Extension: FHIR's primary growth mechanism. Since no standard can cover every clinical edge case, extensions allow you to add custom data (like
birthPlace) while remaining compliant. -
Narrative (
text): Provides a human-readable XHTML summary so that even if a system doesn't "understand" the structured data, a clinician can still read the record.
Key Takeaways for Developers
- Type Reusability: Notice how
Periodis used for names, identifiers, and addresses. Once you learn the structure of aPeriod, you know it everywhere. - The Underscore Pattern: If you see an element like
_birthDate, it means an Extension is being applied to a Primitive type. - Strict Cardinality: Pay attention to arrays
[]. Many FHIR elements (likenameoridentifier) allow multiple entries to handle real-world complexity.
The beauty of FHIR's type system is that once you learn these ~30 datatypes, you can understand ANY FHIR resource. Whether you are looking at a Patient, an Observation, or a MedicationRequest, they are all built from these same consistent blocks.
Top comments (0)