Data Types — the Building Blocks of FHIR

There are 145 resource types in FHIR spanning all of healthcare. Examples are Patient, Procedure, Claim, Condition and Medication.

Each of these resources is made up of a set of elements. Each of these elements is made up of one of FHIR’s pre-defined data types. If my count is correct there are 58 data types in total.

These are the building blocks of FHIR. You cannot add data to FHIR using any other data types.

1. Primitive & General Purpose Data Types

Let’s take a quick look at the Patient resource. In the screenshot below the Type column documents the data types used for each element.

Identifier, boolean, HumanName, ContactPoint, code, date, dateTime, Address and CodeableConcept.

This small example perfectly illustrates the diversity of the different data types, and how most of them fall into one of two categories, Primitive and General Purpose.

Primitive Data Types

Boolean, code, date and dateTime

Anyone who writes code for a living will be familiar with primitives. They’re the most basic elements of data, and usually store a single item. Here are some examples:

  • 123
  • “Darren”
  • false
  • 01/02/1972

Here’s the full list of Primitive data types in FHIR. As the screenshot makes clear, all elements ultimately derive or inherit from the base Element at the center. This is true of all FHIR data types, not just primitives. I’ll go into some detail on that later.

General Purpose Data Types

Identifier, HumanName, ContactPoint, Address, CodeableConcept

We’ve now moved a step up from primitives, where things get a little more complicated. Keeping with the coding analogy, think of general purpose data types as small objects or structures.

Each object contains a number of pieces of connected data that together make up a larger whole. Address is a great example. It contains 10 primitive data elements, each populated with a different piece of data.

  • city
  • postalCode
  • country
  • use

General Purpose data types are not specific to a single FHIR resource. Address is used by Organization and RelatedPerson as well as by Patient.

Here’s the full list of General Purpose data types as used in FHIR R4.

As before, you might notice that all of these different types derive or inherit from Element, and some derive from each other.

Quantity is a good example of this.

Age, Distance, Duration, Count, MoneyQuantity and SimpleQuantity all derive from the Quantity data type. This means they contain all of the attributes of quantity and may or may not contain others.

Did you notice that some of these elements are green and others are yellow?

Green means they are normative — unlikely to change in the future.

Yellow means they are still classed as under trial use. Don’t let this concern you. Trial use elements are close to normative and unlikely to change. You should use them without worry.

2. Metadata and Special Purpose Data Types

I’m not convinced these final two categories of data types are well named. A clearer name might be “Advanced Data Types.”

Meta is an example. It appears in every resource and contains elements such as versionId and lastUpdated. Strangely enough it’s listed under the “Special Purpose” and not the “Metadata” type.

Other examples are Reference, which is used across all resources to store resource references. And Dosage, which is probably the most complex of all the data types. A strong case could be made for turning it into a resource of its own.

Metadata Types

Special Purpose Data Types

3. The Base Element Data Type

One of the reasons I write these emails is that I always learn something when I do. Today is no exception.

I mentioned earlier that all 58 data types derive or inherit from Element. They contain all the attributes of Element, and add their own on top.

Element has two attributes: id and extension.

We’re all at least vaguely familiar with extensions and know that they can be added to the root of a FHIR resource and also to individual elements in a FHIR resource.

You can add an extension to a HumanName and to an Address data type. You can add one to Identifiers and even to Resource References.

But did you know that you could also add an extension to a primitive data type?

We looked at the Patient resource earlier. The patient’s birthDate and deceased state are stored as primitives — a date and a boolean.

Here’s what that looks like as a JSON resource.

So how do you add an extension to birthDate or to deceasedBoolean?

You create a second attribute of the same name prefixed with an underscore. The underscore tells FHIR that you’re accessing the base Element for the primitive data type.

In the example below I added a “Time of year” extension to birthDate and an “Is a zombie” extension to deceasedBoolean.

I also added one more attribute to the base Element for both — an Id.

As I showed earlier, the base Element contains an Extension and an Id attribute.

We’ve all seen and used the Id element at the FHIR resource level. You can also add an Id to every element in FHIR — even primitives such as birthDate.

This is not something most FHIR users are aware of, especially when it comes to primitives.

SDKs often hide this or make it difficult to find, sometimes forcing the developer to code against a similarly named element in order to access the underlying base Element.

Understanding the different FHIR data types and the differences between Primitive and General Purpose data types is important.

Learn more about Data Types: http://hl7.org/fhir/R4/datatypes.html

And more about Primitives: https://hl7.org/fhir/json.html#primitive

---

Ways to Work With Me

Discover more from Darren Devitt

Subscribe now to keep reading and get access to the full archive.

Continue reading