
Type Slicing in FHIR R4
Subscribe to our newsletter
SubscribeFHIR allows resources to introduce polymorphic or choice type elements. A choice type element supports multiple data types. The name of a choice type element always ends with [x]
. A profile can constrain the list of allowed data types of a choice type element and also introduce constraints for specific data types, using an approach called type slicing.
Choice type element renaming
If a profile constrains a choice type element to a single datatype, then FHIR requires the element constraint to be renamed by replacing the [x]
suffix with the name of the associated data type. For example, valueString
indicates a constraint on value[x]
limited to the data type string
.
Changed behavior in R4
FHIR R4 introduces new behavioral rules for type slicing, representing a breaking change from the previous FHIR STU3 specification. The R4 syntax is similar to STU3, but interpreted differently. The new R4 behavior allows more flexibility when authoring choice type constraints.
Type slicing in FHIR STU3
In FHIR STU3, a renamed choice type element constraint (e.g. valueString
) implicitly introduces a type constraint, limiting the choice type element to the associated single data type. The profile rejects all the other data types as specified by the base profile. A profile can only introduce a single renamed choice type element constraint. Multiple renamed element constraints are ambiguous and not allowed.
Example 1:
Extension
Extension.url
Extension.valueString : String
The example STU3 extension definition above constrains the extension value to a single data type string
. The profile rejects extension values in any other data type.
Type Slicing in FHIR R4
In R4, a profile is allowed to introduce multiple renamed element constraints on a choice type element, for different data types allowed by the base profile. A renamed choice type element constraint in a profile represents a set of constraints that apply to a specific data type, which is implied by the element name suffix. A profile can limit the list of allowed datatypes by introducing a constraint on the original [x]
choice type element. However a renamed element constraint does NOT imply a constraint on the list of allowed data types, contrary to STU3. This represents a breaking change.
Example 2:
Extension
Extension.url
Extension.valueString : String
A similar extension definition is interpreted differently in FHIR R4. The renamed choice type element constraint valueString
introduces specific constraints that apply to string values. However the extension definition still allows extension values of other data types.
Example 3:
Extension
Extension.url
Extension.value[x]
Slicing = { ... }
Type = { string }
By introducing type constraints on the original choice type element value[x]
, a profile can limit the list of allowed data types. Example 3 above demonstrates an extension that only allows string values.
Example 4:
Extension
Extension.url
Extension.value[x]
Slicing = { ... }
Type = { string, CodeableConcept }
Extension.valueString
Extension.valueCodeableConcept
Example 4 above demonstrates an extension that allows both string
and CodeableConcept
values. The profile constraints the original value[x]
choice type element to limit the list of allowed data types. The profile also introduces type slices with specific constraints for each of the allowed data types.
Migrating from STU3 to R4
The type slicing syntax introduced in FHIR STU3 is still valid in FHIR R4. However the interpretation is different. In FHIR STU3, renamed element constraints implicitly introduce type constraints. In FHIR R4 you must explicitly constrain the original [x]
choice type element to limit the allowed data types. Therefore it is important to carefully update type slices when migrating profiles from STU3 to R4, specifically extension definitions.
Normalization
In FHIR R4, choice type element renaming is only allowed in the StructureDefinition.differential
component, as a shortcut notation. When generating the StructureDefinition.snapshot
component, renamed choice type element constraints are normalized to the regular slicing syntax, reverting the new element name back to the original name with [x]
suffix (e.g. value[x]
) and initializing the slice name from the new element name (e.g. valueString
).
Example 5:
StructureDefinition.differential
...
valueString
valueCodeableConcept
...
StructureDefinition.snapshot
...
value[x] : valueString
value[x] : valueCodeableConcept
...
The normalization ensures that consumers of snapshots, such as validator components, will never encounter renamed elements, thereby reducing the complexity of the implementation. All logic involving element renaming is contained within the snapshot generator itself.
Normalizing structural constraints to a well defined “canonical” format also facilitates the comparison of profiles.
Forge 22.1 for R4
Forge release 22.1 for FHIR R4 implements the updated R4 type slicing behavior. Specifically, renamed choice type element constraints are now always rewritten to normalized slice syntax in the generated snapshot component.
Also, we have now implemented a common set of unit tests for the snapshot generator, as published and maintained by the HL7 FHIR community. This allowed us to discover and fix some bugs in the .NET and Java implementations of the snapshot generator, decrease discrepancies between implementations and improve quality of the generated output.
You can download Forge for free from Simplifier.
Happy profiling!
2 thoughts
>In FHIR R4, choice type element renaming is only allowed in the StructureDefinition.differential component, as a shortcut notation. When generating the StructureDefinition.snapshot component, renamed choice type element constraints are normalized to the regular slicing syntax, reverting the new element name back to the original name with [x] suffix (e.g. value[x]) and initializing the slice name from the new element name (e.g. valueString).
I cannot find the place in the specification talking about this “normalization”. Where does it come from?
Hi Ivan,
I understand this is not explicitly in the spec, but rather one of those details discussed in various places (tracker items, FHIR-I calls, at DevDays). A few pointers my colleagues provided me with:
* This tracker item: https://jira.hl7.org/browse/FHIR-12259, but the resolution doesn’t capture everything.
* This Zulip discussion: https://chat.fhir.org/#narrow/stream/179177-conformance/topic/Slicing.20a.20non-repeating.20element
Perhaps that Zulip thread would be a good place to ask for any further clarification.
Hope this helps,
Ward