How to work with Сoded FHIR data types, Code Systems and Value Sets in FHIR
Let’s start by looking at how coded data types are used in FHIR. At its simplest, coded value in FHIR can be represented with a single string. An example of that is the patient's gender as shown below:
As we can see from the short description, it is expected for gender
to be set in one of the following values: male
, female
, other
, or unknown
. It is just a text description, but the actual values are contained in the AdministrativeGender Value Set that the element is binded to. We can see that the binding strength for this element is “required,” meaning that no values, other than the ones listed in the AdministrativeGender Value Set, can be used for this element.
But since the FHIR Specification is so generic and aimed at solving problems of sharing clinical records between different providers in different countries that all have different regulations, it is a rare case to have a single Code System cover all the needs of an element coding. That is when the Coding
data type comes in handy.
Coding is a complex data type that consists of not only a code, but also a link to the Code System it comes from, the version of the system, and, optionally, a display.
If we look at the connectionType
in the Endpoint resource we can see this data type in use:
The element is binded to the Endpoint Connection Type Value Set, but the binding strength for this element is not “required” unlike the previous example. In this case, the binding is“extensible,” meaning that using this Value Set would be preferred but is not necessary. As such, it’s necessary to indicate whether a given code comes from the Endpoint Connection Type
code system or another. In a resource, it would look like this:
Example
"connectionType": {
"system": "http://terminology.hl7.org/CodeSystem/endpoint-connection-type",
"code": "hl7-fhir-rest",
"version": "4.0.1",
"display": "Interact with the server interface using FHIR's RESTful interface. For details on its version/capabilities you should connect the value. Endpoint.address and retrieve the FHIR CapabilityStatement"
}
However, oftentimes one code is not enough to cover a codeable concept; different systems may use different dictionaries, or there may not even be a dictionary that describes the concept yet. Therefore, the CodeableConcept data type is the most widely used type for coding values. It consists of an array of Codings that may present a single codeable concept in different systems, as well as a text
element in case the value can’t be presented using the existing code systems or when additional transcription is required.
For example, let’s say we want to record a body weight observation, and we have two different dictionaries in the system that describe code for body weight: SNOMED and LOINC. As we can see from the specification for Observation Resource content, the code
element here is a single object, rather than an array, but its type is set to CodeableConcept:
This means we can use two elements of coding
array to present our codes:
Example
The reason why the code
element is a single object, but not an array, is because all of the codes provided in it represent a single codeable concept that has the same meaning across different code systems.
In addition, Quantity, string, and uri can also carry coded values or content that can be treated as a code and bound to a value set.
So, a Code System defines concepts and gives them meaning through definitions, as well as assigns codes that represent these concepts. But if we look through Observation Resource content, we find that the same Code System, SNOMED, is now used in a different context:
Instead of describing observation codes, it is referred to as a dictionary for Body Structures. How does this work? Some Code Systems, such as LOINC, SNOMED, and UCUM can contain thousands of codes that can be applicable in different contexts. That’s why we use Value Sets; while a Code System defines the content of a dictionary, Value Set defines the context. Let’s take a look at a Condition Resource content. SNOMED code system occurs twice here:
First, it’s used in the bodySite
element and defines codes for body structures, and then it’s used in the evidence
element and defines clinical findings. The contexts here are managed through different Value Sets.
The first Value Set, body-site, simply lists the concepts from SNOMED that represent Body Structures:
Example
"compose" : {
"include" : [{
"system" : "http://snomed.info/sct",
"concept" : [{
"code" : "53075003",
"display" : "Distal phalanx of hallux"
},
{
"code" : "76986006",
"display" : "Distal phalanx of second toe"
},
{
"code" : "65258003",
"display" : "Distal phalanx of third toe"
},
{
"code" : "54333003",
"display" : "Distal phalanx of fourth toe"
},
…
{
"code" : "29850006",
"display" : "Iliac crest"
}]
}]
}
The second one, clinical-findings, uses a filter option to restrict codes from a code system:
Example
Only codes nested in concept "404684003" will be included in a Value Set. You can read more about the Concept of Hierarchy here. But how can we know which concepts result in being part of the Value Set? An operation $expand can help with that. If you call operation $expand on the Value Set as shown below, you will see all the concepts that are part of the Value Set:
Example
Thus, coded data types in FHIR can be presented through a code
, coding
, or codeableConcept
data type.
Coding and CodeableConcept references a Code System that assigns codes representing the concepts in the system, such as LOINC or SNOMED. The Value Set defines a context in which a CodeSystem can be used and which part of it is applicable.