DEV Community

Cover image for Understanding FHIR Data Types
Paul Aderoju
Paul Aderoju

Posted on

Understanding FHIR Data Types

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"
      }
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

Let's Dive into the Data Types

1. Primitive Types (Simple Values)

  • String: A sequence of Unicode characters (Max 1MB).
  • Boolean: Strict true or false.
  • 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 a value.
  • 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 start and an optional end.

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

  1. Type Reusability: Notice how Period is used for names, identifiers, and addresses. Once you learn the structure of a Period, you know it everywhere.
  2. The Underscore Pattern: If you see an element like _birthDate, it means an Extension is being applied to a Primitive type.
  3. Strict Cardinality: Pay attention to arrays []. Many FHIR elements (like name or identifier) 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)