Creating examples

Examples are probably one of the more useful things to an implementer – yet likely the least exciting part of building an Implementation Guide (IG) to the designer. And not only are they useful to the implementer, they are a good way to double check the actual IG – it’s surprising how often having to create an example finds issues with the artifacts within an IG.

But the tooling to create examples is not that great. Generally you’re using a generic JSON or XML tool which offers no editing support to ensure that the example is valid (you can use the $validate operation that I’ve discussed before, but the workflow is tedious). I’ve tried to use clinFHIR for that – and it does work, though chokes some of the more complex profiles, and is still quite slow to create the resource instance.

There is an alternative that I’m currently using that seems to resolve these issues – the shorthand spec (with associated sushi reference implementation) that I blogged about last week. As well as producing profiles, it can also create resource instances using the same syntax as for profiles, and even better – when you run sushi to generate the resources, it will pick up the more egregious errors.

If you nominate a profile when you create the instance, it will check compliance with that profile – to some degree at least. (It doesn’t do any  terminology checking for example – but it’s way better than doing it by hand).

Another benefit to using Shorthand / sushi for examples is that the text is understandable to non-technical people as well – and it’s easy to include comments. Admittedly it does require a basic understanding of FHIR – but well within the reach of a Clinician or BA.  I’ve started using it in a project I’m working on – and the response so far has been positive.

So let’s take a look at an example – and call out some of the specifics that are useful to know. The following snippet is for a Patient instance that is compliant with the Profile we’re generating for the NHI project in New Zealand. This is a reasonably complex profiles that includes:

  • simple extensions
  • complex extensions
  • extensions on primitives
  • slicing

and plenty of coded elements! It’s not yet complete, but will hopefully demonstrate the point.


Instance:   patient2
InstanceOf: NhiPatient

* text.div = "<div xmlns='http://www.w3.org/1999/xhtml'>John Doe</div>"
* text.status = #additional

//name. The source of the name was a NZ Visa
* name.family = "Doe"
* name.given = "John"
* name.given[1] = "Albertus"
* name.extension[informationsource].valueCodeableConcept.coding.system = "http://standards.digital.health.nz/fhir/ValueSet/nzinfosource"
* name.extension[informationsource].valueCodeableConcept.coding.code = #NZPV
* name.extension[informationsource].valueCodeableConcept.coding.display = "New Zealand Permanant visa"

* gender = #male

//Birth date, verified by passport
* birthDate = "1989-12-12"
* birthDate.extension[informationsource].valueCodeableConcept.coding.system = "http://standards.digital.health.nz/fhir/ValueSet/nzinfosource"
* birthDate.extension[informationsource].valueCodeableConcept.coding.code = #PPRT
* birthDate.extension[informationsource].valueCodeableConcept.coding.display = "Passport"

//the current NHI
* identifier.use = #official
* identifier.system = "https://standards.digital.health.nz/id/nhi"
* identifier.value = "WER4568"

//a dormant (replaced)  NHI
* identifier.use = #old
* identifier.system = "https://standards.digital.health.nz/id/nhi"
* identifier.value = "ABC1234"

//ethnicity is 'not stated'
* extension[ethnicity].valueCodeableConcept.coding.system = "https://standards.digital.health.nz/codesystem/ethnic-group-level-4"
* extension[ethnicity].valueCodeableConcept.coding.code = #9999
* extension[ethnicity].valueCodeableConcept.coding.display = "Not Stated"

//email address and phone
* telecom.system = #email
* telecom.value = "johndoe@erewhon.com"
* telecom[1].system = #phone
* telecom[1].value = "+64 9 000 0000"

//physical address
* address.line = "23 Thule St"
* address.city = "Waipu"

//DHB (from address) is Counties Manakau DHB (Assuming that Organization1 is the DHB)
* extension[dhb].valueReference = Reference(organization1)

//born in Palmerston North, New Zealand. Verified by passport
* extension[patient-birthPlace].extension[placeOfBirth].valueString = "Palmerston North"

//birth country New Zealand. The XXX is temporary, due to some current limitations with the shorthand generator
* extension[patient-birthPlace].extension[countryXXX].valueCodeableConcept.coding.system = "http://hl7.org/fhir/ValueSet/iso3166-1-2"
* extension[patient-birthPlace].extension[countryXXX].valueCodeableConcept.coding.code = #NZ
* extension[patient-birthPlace].extension[countryXXX].valueCodeableConcept.coding.display = "New Zealand"

//source of information about the birthplace was a passport
* extension[patient-birthPlace].extension[sourceXXX].valueCodeableConcept.coding.system = "http://standards.digital.health.nz/fhir/ValueSet/nzinfosource"
* extension[patient-birthPlace].extension[sourceXXX].valueCodeableConcept.coding.code = #PPRT
* extension[patient-birthPlace].extension[sourceXXX].valueCodeableConcept.coding.display = "Passport"

//The general practitioner is described by the practitionerrole1 resource (has references to Practitioner & Organization)
* generalPractitioner = Reference(practitionerrole1)

//The patient is of maori descent...
* extension[patient-maoriDescent].valueCodeableConcept.coding.system = "http://standards.digital.health.nz/fhir/ValueSet/nzmaoridescent"
* extension[patient-maoriDescent].valueCodeableConcept.coding.code = #yes

//... and belongs to the Tainui iwi
* extension[patient-iwi].valueCodeableConcept.coding.system = "http://standards.digital.health.nz/fhir/ValueSet/nziwi"
* extension[patient-iwi].valueCodeableConcept.coding.code = #2001
* extension[patient-iwi].valueCodeableConcept.coding.display = "Tainui"



Let’s go through this and point out the salient points.

Line 1 indicates that this shorthand defines a instance (rather than a profile), and that the id will be ‘patient2’
Line 2 states that the instance will be compliant with the profile that has the id ‘NhiPatient’. This profile needs to be available to sushi – either created by it or an external one. You can use a core resource type like Patient if you want.
Lines 4-5 create a simple text element. Note the ‘*’ at the front of the line that indicates that we are setting a value. This is used throughout the text.
Lines 7 – 13 describe the patients name (John Albertus Doe), and includes an extension to indicate that information was sourced from a visa (remember that this is a registry so data source is important. Actually, as I write this I realize that there may be better ways of doing this – we should maybe look at the VerificationResult resource, but I digress…).

In line 10, the second given name has an indexer (that’s the number in brackets) that indicates that ‘Albertus’ is the second given name (Indexers start at 0). Indexers are only needed for elements that can occur more than once – and can be left off the first one (which is why it’s not present on line 9 – although you can add it in if you wish). You see the same thing on line 41 for telecom.

The extension on lines 11-13 utilize the ability of shorthand to refer to an extension by its name. What it’s saying is that there is an extension named ‘informationsource‘ that sushi can access. This is a simple extension with a single CodeableConcept, and the instance specifies the system, code and display. Note that the code value is not in quotes – it has a hash (#) in front. When sushi runs, it will check that the information in the instance matches what is defined in the extension – if not, an error is raised. It will also check that the profile allows this extension to be present at this location. This checking is really handy!

The birth date in lines 17-21 have the same extension (different values of course).

Lines 23 – 31 have a couple of identifiers note that the system is the same, but use value indicates which is current, and which has been replaced (is dormant).

In line 52 we have a complex extension – an extension that has children. The extension name is patient-birthplace, and within that extension is a child called placeOfBirth. (There are other possible child elements that are possible – the extension definition is shown below). Again, sushi will check that these names are correct, and that the profile supports this extension at this place. (Note that the XXX is a temporary measure to deal with a current limitation of sushi).

The remainder of the example is (or hopefully should be) straightforward, being variants on what we’ve already discussed.

And here are the extensions that we’re using. The information source:

Extension: Informationsource
Id: informationsource
Description: "The source of the information"
//These files were generated by a script from a model at NzNHIPatient.dateOfDeath.source

* extension 0..0
* value[x] only CodeableConcept
* valueCodeableConcept from http://standards.digital.health.nz/fhir/ValueSet/dodinfosource (preferred)

and the patient birthplace:

Extension: Patient_birthPlace
Id: patient-birthPlace
Description: "The country where the person was born"
//These files were generated by a script from a model at NzNHIPatient.countryOfBirth

* extension contains
countryXXX 0..1 and
placeOfBirth 0..1 and
source 0..1

// definitions of sub-extensions
* extension[countryXXX].url = "countryXXX"
* extension[countryXXX] ^definition = "The birth country."
* extension[countryXXX].value[x] only CodeableConcept
* extension[countryXXX].valueCodeableConcept from http://hl7.org/fhir/ValueSet/iso3166-1-2 (preferred)

* extension[placeOfBirth].url = "placeOfBirth"
* extension[placeOfBirth] ^definition = "No description"
* extension[placeOfBirth].value[x] only string

* extension[sourceXXX].url = "sourceXXX"
* extension[sourceXXX] ^definition = "The source of information concerning the country of birth"
* extension[sourceXXX].value[x] only CodeableConcept
* extension[sourceXXX].valueCodeableConcept from http://standards.digital.health.nz/fhir/ValueSet/nzinfosource (required)

Note that extension definitions can also indicate the ValueSet to be used for coded elements.

And note also that some of the elements have ‘XXX’ at the end. This is due to a limitation in sushi right now that prevents extension names from being reused (someone else used ‘country’ in an extension, so we can’t!)

So that’s it – hopefully you’ll agree that shorthand (and sushi) go a long way towards making it easier to produce understandable examples – certainly way better than hand editing json or XML.

And a reminder that Shorthand (and sushi) is very much a work in progress – expect to see improvements as time goes on, and potentially changes to the syntax…

About David Hay
I'm an independent contractor working with a number of Organizations in the health IT space. I'm an HL7 Fellow, Chair Emeritus of HL7 New Zealand and a co-chair of the FHIR Management Group. I have a keen interest in health IT, especially health interoperability with HL7 and the FHIR standard. I'm the author of a FHIR training and design tool - clinFHIR - which is sponsored by InterSystems Ltd.

3 Responses to Creating examples

  1. Ward says:

    Another great post on Shorthand!

    For example generation, you should also give the example generation (filled with some simple data or empty) on Simplifier.net, which I recently explained here: https://twitter.com/WardWeistra/status/1207295952777699335.

    It isn’t perfect and only available for STU3 at the moment, but it can save you some time with an editor and validator directly available. At some point we can of course also show the Shorthand version for enhanced readability, once Hatchery is available 🙂

  2. Pingback: 3 Primary Goals of Digital Marketing in India - Moawad Skin Institute (MSI)

Leave a Reply

Discover more from Hay on FHIR

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

Continue reading