This blog is a continuation of the previous post titled “Introduction to FHIR.” Please read that article before proceeding with this one to gain necessary context. In this article, we will delve deeper into the concept of FHIR resources, exploring their structure, purpose, and how they interconnect to represent healthcare data effectively. By understanding these resources, we can gain valuable insights into how FHIR facilitates interoperability and standardization in healthcare information systems.
Let’s explore how to read a FHIR resource defined in JSON. Refer to this guide to understand the general JSON representation. For a specific example, check out this page for details of an Organization resource. Be sure to view the JSON tab to see its JSON representation. We’ll dive deeper into this resource in our next blog post.
For now understanding the structure and components of FHIR resources is crucial for effectively working with healthcare data in a standardized format. FHIR resources are designed to represent various healthcare concepts and entities in a consistent and interoperable manner. By examining the different data types, references, and identifiers used within these resources, we can gain a comprehensive understanding of how FHIR organizes and connects healthcare information. Let’s delve into each of these key aspects to build a solid foundation for working with FHIR resources.
We have to discuss 6 points when it comes to the data we have in resources. They are
– Data type (Primitive) – Data type (Complex) – Reference – Identifier – Coding (Complex data type) – CodeableConcept
Here’s a concise summary of the primitive data types in FHIR:
boolean: Represents true or false values. – Example: A Patient resource might use a boolean to indicate whether the patient is currently active (active: true).
integer: Represents whole numbers. – Example: An Observation resource might use an integer to record the number of heartbeats per minute in a vital signs report (heartRate: 72).
decimal: Represents numbers with decimal points. – Example: A MedicationRequest resource could use a decimal value to record the exact dosage of medication prescribed (dose: 1.5).
string: Represents sequences of characters. – Example: A Practitioner resource might store a doctor’s name using the string data type (name: “Dr. Jane Smith”).
uri: Represents Uniform Resource Identifiers. – Example: In a DocumentReference, the uri can be used to store the URL of a document (url: “http://example.com/report.pdf”).
date: Represents dates (e.g., YYYY-MM-DD). – Example: The date field in a Procedure resource could indicate when a surgery took place (date: “2023-09-15”).
dateTime: Represents dates and times (e.g., YYYY-MM-DDThh:mm:ss). – Example: A DiagnosticReport resource might use dateTime to store the exact time a lab result was generated (issued: “2024-05-12T14:00:00”).
time: Represents times (e.g., hh:mm:ss). – Example: A MedicationAdministration resource could use the time primitive type to specify the exact time a medication was administered (effectiveTime: “14:30:00”).
code: Represents coded values (a string with a limited set of possible values). – Example: In a Condition resource, the clinicalStatus field might use a code to represent whether the condition is active or resolved (code: “active”).
id: Represents unique identifiers. – Example: A Patient resource might have an id to uniquely identify it within the FHIR system (id: “12345”).
oid: Represents Object Identifiers (a special type of identifier). – Example: A Patient resource could use an oid to reference an official identifier, such as one from a national healthcare registry (system: “urn:oid:1.2.36.146.595.217.0.1”).
uuid: Represents Universally Unique Identifiers. – Example: In a Bundle resource, UUIDs might be used to uniquely identify resources within a collection of healthcare data (id: “urn:uuid:550e8400-e29b-41d4-a716-446655440000”).
markdown: Represents text formatted using Markdown. – Example: A Questionnaire resource might use markdown to provide instructions for how to fill out the form (div: “<div xmlns=’http://www.w3.org/1999/xhtml’><p><strong>Please fill out all sections.</strong></p><p>Use a *pen* for written responses.</p></div>”).
These types are the building blocks for more complex data structures in FHIR. In the above JSON structure example of keys holding primitive data are active, name, and alias. active and name are straight forward but alias is an array where each of the items in that array is a primitive data type, in this case a string. Read more here.
Here’s an overview of some complex data types in FHIR:
Address: Represents postal addresses, including fields like street, city, state, postal code, and country. – Example: A Patient resource could use Address to store where the patient lives:
{ "address": { "line": ["123 Main Street"], "city": "Springfield", "state": "IL", "postalCode": "62704", "country": "USA" } }
Attachment: Represents content in a specific format, such as a document or image, including fields like URL, title, and content type. – Example: A DocumentReference resource could use an Attachment to store a PDF of a medical report.
{ "contentType": "application/pdf", "url": "http://example.com/report.pdf", "title": "Medical Report" }
CodeableConcept: Represents a concept that can be coded in multiple ways, including fields like coding (a list of codes) and text (a human-readable description). – Example: A Condition resource might use a CodeableConcept to represent a diagnosis.
{ "coding": [ { "system": "http://snomed.info/sct", "code": "44054006", "display": "Diabetes mellitus type 2" } ], "text": "Type 2 Diabetes" }
Coding: Represents a single code from a code system, including fields like system (the code system), code, and display (a human-readable description). – Example: A Procedure resource might use a Coding to represent a specific procedure.
{ "system": "http://www.ama-assn.org/go/cpt", "code": "12345", "display": "Appendectomy" }
ContactPoint: Represents contact details, including fields like system (phone, email), value (the actual contact detail), and use (home, work). – Example: A Patient resource might use a ContactPoint to store a phone number.
{ "system": "phone", "value": "+1-555-555-5555", "use": "home" }
HumanName: Represents a human name, including fields like family (last name), given (first name), and prefix (e.g., Mr., Dr.). – Example: A Practitioner resource might use HumanName to record the doctor’s full name:
{ "name": { "family": "Doe", "given": ["John"], "prefix": ["Dr."] } }
Identifier: Represents an identifier for an entity, including fields like system (the namespace for the identifier) and value (the actual identifier). – Example: A Patient resource might use an Identifier to store a medical record number.
{ "use": "official", "system": "http://hospital.com/patient-ids", "value": "123456" }
Period: Represents a time period, including fields like start and end. – Example: A MedicationRequest resource might use a Period to specify the duration of a prescription.
{ "start": "2024-01-01", "end": "2024-12-31" }
Quantity: Represents a measured amount, including fields like value (the numerical value), unit (the unit of measure), and system (the code system for the unit). – Example: An Observation resource might use a Quantity to record a patient’s weight.
{ "value": 70, "unit": "kg", "system": "http://unitsofmeasure.org", "code": "kg" }
Range: Represents a range of values, including fields like low and high. – Example: A DiagnosticReport resource might use a Range to specify normal blood pressure values.
{ "low": { "value": 80, "unit": "mmHg" }, "high": { "value": 120, "unit": "mmHg" } }
Ratio: Represents a ratio of two quantities, including fields like numerator and denominator. – Example: A Medication resource might use a Ratio to specify the concentration of a solution.
{ "numerator": { "value": 1, "unit": "mg" }, "denominator": { "value": 1, "unit": "mL" } }
Reference: Represents a reference to another resource, including fields like reference (the actual reference) and display (a human-readable description). – Example: A Condition resource might use a Reference to link to a Patient resource.
{ "subject": { "reference": "Patient/1234", "display": "John Doe" } }
SampledData: Represents a series of measurements taken at regular intervals, including fields like origin, period, and data. – Example: An Observation resource might use SampledData to record a series of heart rate measurements.
{ "origin": { "value": 0, "unit": "bpm" }, "period": 1000, "factor": 1, "lowerLimit": 60, "upperLimit": 100, "dimensions": 1, "data": "72 75 78 80 76 74" }
Signature: Represents a digital signature, including fields like type, when, and who. – Example: A Consent resource might use a Signature to record a patient’s consent.
{ "type": [ { "system": "http://hl7.org/fhir/valueset-signature-type", "code": "1.2.840.10065.1.12.1.1", "display": "Author's Signature" } ], "when": "2024-09-30T14:36:18+05:30", "who": { "reference": "Practitioner/123" } }
Timing: Represents timing schedules, including fields like event (specific times), repeat (rules for repeating), and code (a code for the timing). – Example: A MedicationAdministration resource might use Timing to specify the schedule for administering a medication.
{ "event": ["2024-09-30T14:36:18+05:30"], "repeat": { "frequency": 1, "period": 24, "periodUnit": "h" }, "code": { "coding": [ { "system": "http://terminology.hl7.org/CodeSystem/timing-abbreviation", "code": "QD", "display": "every day" } ] } }
These complex types are used to build more detailed and structured data in FHIR. In the above JSON structure example of keys holding primitive data are type, telecom, address, etc. All of these are actually an array where each of the items in that array is of the specified complex data type. Read more [here](https://hl7.org/fhir/R4/datatypes.html#complex).
Reference is a complex data type in FHIR, deserving its own section due to its importance and unique nature. A reference allows one resource to refer to another. This is a key mechanism for building relationships between different resources, such as linking a `Patient` resource to an associated `Practitioner` or `Encounter`. These references make FHIR highly flexible and scalable, allowing for comprehensive healthcare data management.
FHIR supports two main types of references:
Internal References (contained): These are references to resources within the same resource. For example, a `Bundle` resource might contain multiple related resources, like `Patient` and `Observation`. These contained resources are self-contained within the main resource and do not exist independently. – Example: An `Observation` resource might internally reference a patient:
{ "subject": { "reference": "#patient1" } }
External References: These refer to resources that are external to the current resource. For example, a `Condition` resource can refer to a `Patient` resource by using a reference to the `Patient`’s URL (e.g., `Patient/1234`). This allows the `Condition` to link to any existing `Patient` resource on the FHIR server. – Example: A `Condition` resource could reference a patient on a FHIR server:
{ "subject": { "reference": "http://example.com/fhir/Patient/1234", "display": "Jane Doe" } }
The structure of a Reference is as follows. Read more here.
{ // from Element: extension "reference" : "<string>", // C? Literal reference, Relative, internal or absolute URL "type" : "<uri>", // Type the reference refers to (e.g. "Patient") "identifier" : { Identifier }, // Logical reference, when literal reference is not known "display" : "<string>" // Text alternative for the resource }
reference: The actual reference to the related resource. This could be a URL, an ID within the server, or an internal reference to a contained resource. type: The name of the resource this reference is referring to. display: A human-readable name or description of the referenced resource, often for convenience in user interfaces. identifier: An additional identifier that can help find the resource in case the reference is not available or the ID is insufficient.
Example:
{ "reference": "Patient/1234", "display": "John Doe" }
An identifier in FHIR is a unique string or number assigned to a resource to distinguish it from other resources. Identifiers are critical for ensuring that resources, such as `Patient`, `Practitioner`, or `Observation`, can be accurately tracked and referred to across systems, organizations, and contexts.
In healthcare, a single patient or practitioner might be referenced by multiple identifiers across different systems, such as a hospital, insurance provider, or government registry. An identifier in FHIR consists of several components that help clearly define the source and meaning of the identifier.
{ // from Element: extension "use" : "<code>", // usual | official | temp | secondary | old (If known) "type" : { CodeableConcept }, // Description of identifier "system" : "<uri>", // The namespace for the identifier value "value" : "<string>", // The value that is unique "period" : { Period }, // Time period when id is/was valid for use "assigner" : { Reference(Organization) } // Organization that issued id (may be just text) }
value: The actual identifier string or number (e.g., a patient’s medical record number, national ID, or insurance number). system: The system that assigns the identifier. This could be a specific registry, hospital system, or national identifier system, often represented by a URI (e.g., `http://hospital.com/patient-id-system`). use: This indicates how the identifier is used, such as for official purposes, temporary identifiers, or secondary use (e.g., `usual`, `official`, `temp`, `secondary`). type: A code that classifies the identifier, such as whether it’s a social security number, a medical record number, or another specific type. assigner: The organization or individual responsible for assigning the identifier.
Example: A `Patient` resource might contain multiple identifiers, such as a medical record number and an insurance number:
{ "identifier": [ { "use": "official", "system": "http://hospital.com/patient-ids", "value": "123456" }, { "use": "secondary", "system": "http://insurance.com/plan-ids", "value": "78910" } ] }
Identifiers are crucial because they allow resources to be matched or linked across various healthcare systems. For example:
– A patient may be given different IDs at different hospitals or clinics, but an identifier ensures the patient’s information remains connected across systems. – Insurance companies use identifiers to manage claims and link to patient data. – Governments may assign national health identifiers to track patient care across a country.
– Multiple Identifiers: A resource like a `Patient` may have multiple identifiers, each for different systems (hospital, insurance, etc.). – Global Uniqueness: An identifier should be unique within the context of the system that issued it. However, different systems may assign their own identifiers, so the `system` field is essential for clarifying which system the identifier belongs to. – Identifier Types: Using the `type` field, FHIR allows systems to categorize identifiers (e.g., `SSN`, `MRN`, `Driver’s License`).
In FHIR, there are both primitive and complex data types. The **code** primitive type represents a string that conforms to a value set, typically a coded value. However, the **Coding** complex data type is more nuanced and is designed for scenarios where additional context or structure is required. This section will focus on the **Coding** as a **complex data type** and not the **primitive data type**.
The Coding complex data type is used to provide codes that carry more contextual meaning, often derived from a predefined set of concepts, known as code systems (such as ICD-10, SNOMED CT, or LOINC). Unlike a primitive `code`, which is just a string, the complex Coding often includes more metadata.
The structure of a Coding is as follows. Read more here.
{ // from Element: extension "system" : "<uri>", // Identity of the terminology system "version" : "<string>", // Version of the system - if relevant "code" : "<code>", // Symbol in syntax defined by the system "display" : "<string>", // Representation defined by the system "userSelected" : <boolean> // If this coding was chosen directly by the user }
system: The system from which the code is derived (e.g., SNOMED CT, ICD-10). version: The version of the coding system. display: A human-readable representation of the code, which gives more context for clinicians or users reading the data. code: The actual code itself, which is often just a string but must conform to the rules of the associated coding system.
For example, if you want to record a diagnosis using a code from the SNOMED CT system, you might use a complex Coding type that references SNOMED CT as the system and provides both the code and a human-readable display.
Example: A `Condition` resource representing a diagnosis might use `Coding` to record the diagnosis using SNOMED:
{ "coding": [ { "system": "http://snomed.info/sct", "code": "44054006", "display": "Type 2 Diabetes Mellitus" } ] }
In this example:
– The `system` identifies the coding system (SNOMED CT). – The `code` is the actual code value. – The `display` is a human-readable term that makes the code understandable.
The Coding complex type is often used when working with coded data that needs to be universally understood by different systems or organizations. It ensures that the code is interpreted correctly regardless of the system in use.
– Diagnoses and Conditions: Assigning medical codes from systems like ICD-10 or SNOMED CT to clinical conditions. – Medications: Coding drug formulations using standard drug terminologies. – Procedures: Recording clinical procedures with code systems like CPT or LOINC.
By using this type, FHIR enables systems to standardize and communicate clinical data in a meaningful and interoperable way, ensuring accurate interpretation across different systems.
In FHIR, the CodeableConcept is a flexible and powerful complex data type used to represent codes from a coding system. It is more comprehensive than the simple code or Coding data types, as it allows for multiple codes from different systems to be associated with a single concept. This section explains the CodeableConcept complex data type and its importance in FHIR.
The CodeableConcept data type is designed to capture a concept that can be represented by multiple codes, possibly from different coding systems. It allows for the use of codes in combination with human-readable text, ensuring both machine-processable and human-readable content.
{ // from Element: extension "coding" : [{ Coding }], // Code defined by a terminology system "text" : "<string>" // Plain text representation of the concept }
coding: A list of `Coding` elements that reference specific codes from one or more code systems (e.g., SNOMED CT, ICD-10, LOINC). text: A human-readable version of the concept to ensure clarity when the coding is not sufficient or when codes from different systems need to be understood in context.
The CodeableConcept is particularly useful when:
– Multiple coding systems need to be referenced for the same concept. – The concept can be expressed in various ways across different systems, but all relate to the same idea. – There is a need for both coded data and human-readable descriptions.
Here’s an example of the CodeableConcept in action:
{ "coding": [ { "system": "http://loinc.org", "code": "1234-5", "display": "Hemoglobin" }, { "system": "http://snomed.info/sct", "code": "721981007", "display": "Blood test for hemoglobin" } ], "text": "Hemoglobin blood test" }
– The `coding` element contains multiple `Coding` entries from different systems (LOINC and SNOMED CT), both representing the same clinical concept—hemoglobin testing. – The `system` fields identify the code systems used (LOINC and SNOMED CT). – The `code` fields contain the actual codes. – The `display` fields provide human-readable names for each code. – The `text` field offers an additional human-readable description of the concept.
The CodeableConcept data type is widely used in healthcare for many scenarios where multiple coding systems or representations of a single concept are necessary. It provides the flexibility to encode the same concept in various ways while maintaining interoperability and clarity.
Some common use cases include:
– Conditions and Diagnoses: A patient’s diagnosis can be represented by multiple codes from different systems like ICD-10 and SNOMED CT. – Lab Results: A lab test may have codes from LOINC, but could also include SNOMED CT codes or a local terminology system. – Medications: Representing a medication using codes from both RxNorm and a proprietary drug database.
By using CodeableConcept, FHIR allows systems to integrate information from different coding systems into a single coherent concept, ensuring both flexibility and precision in medical data representation.
FHIR provides a comprehensive framework for representing and exchanging healthcare data across systems. By using well-defined resources and data structures like Reference, CodeableConcept, and others, healthcare providers can ensure seamless interoperability and more efficient care. This post has demonstrated how even a simple hospital workflow can leverage various FHIR resources to manage complex data scenarios. Whether you are developing an API or integrating FHIR into existing systems, understanding the structure and relationships between these resources is key to building reliable, interoperable solutions for healthcare. As FHIR continues to evolve, its flexibility and powerful data modeling capabilities make it an invaluable tool for healthcare technology.
1. HL7 FHIR R4 Data Types – Coding: https://hl7.org/fhir/R4/datatypes.html#codesystem 2. HL7 FHIR R4 Data Types – CodeableConcept: https://hl7.org/fhir/R4/datatypes.html#codeableconcept 3. SNOMED CT: http://snomed.info/sct 4. LOINC: http://loinc.org 5. American Heart Association: https://www.heart.org/en/affiliates/california/orange-county 6. World Health Organization – Cardiovascular diseases: https://www.who.int/health-topics/cardiovascular-diseases#tab=tab_1