HL7 FHIR represents the next generation healthcare interoperability standard and tries to combine the good stuff from older standards yet leveraging (somewhat) modern things like JSON, XML, HTTP and REST.
With BizTalk you can use the XML-schemas found on the main FHIR site. As BizTalk is all about XML it’s a perfect match.
A side note is that FHIR does not use any versioning in its namespace which will lead to problems if you need more than one version deployed. As usual this can be solved by modifying the namespace in and out of BizTalk using a namespace altering pipeline component.
While FHIR resources can be represented in XML they also can come dressed in JSON. Lets have a look at how we can handle that in BizTalk.
If we try to use the out-of-the-box pipeline components in BizTalk 2013 R2 for JSON –> XML conversion (or any other non-FHIR aware json decoder) the generated XML will not conform with the the FHIR-schemas and specification. The differences are highlighted here http://hl7.org/fhir/json.html#xml but two key ones are:
- How FHIR resource type are defined.
- In XML its the actual root-node name
- In JSON its the ‘resourceType’ field.
- Values are normally placed in a xml attribute instead of in the elements.
Lets look at a simplified example with a FHIR “Encounter” in JSON and HTTP POST it to a BizTalk (WCF-WebHttp) ReceiveLocation using a pipeline with the new and out-of-the-box BizTalk 2013R2 JSON Decoder.
After the pipeline the XML looks like this:
This does NOT match the FHIR schema.
To solve this we need a “FHIR aware” JSON to XML Decoder. Luckily there is a great open source one for .NET called .NET API for HL7 FHIR. It´s a really feature rich API that can do a lot more than just FHIR JSON and XML conversion!
Lets create a BizTalk pipeline component using .NET API for HL7 FHIR.
public partial class FhirJsonDecoder : IComponent, IBaseComponent, IPersistPropertyBag, IComponentUI
//Execute is the main method invoked every time a message passes the pipeline component
public IBaseMessage Execute(IPipelineContext pc, IBaseMessage inmsg)
IBaseMessagePart bodyPart = inmsg.BodyPart;
if (bodyPart != null)
using (Stream originalDataStream = bodyPart.GetOriginalDataStream())
if (originalDataStream != null)
//Read the json message
using (TextReader tr = new StreamReader(originalDataStream))
json = tr.ReadToEnd();
//Use FHIR-NET-API to create a FHIR resource from the json
//This 'breaks' the stream a puts the complete message into memory
ResourceReader resourceReader = new Hl7.Fhir.Serialization.ResourceReader(FhirParser.FhirReaderFromJson(json));
//Use FHIR-NET-API to serialize the resource to XML
byte resourceXmlBytes = Hl7.Fhir.Serialization.FhirSerializer.SerializeToXmlBytes(resourceReader.Deserialize());
//Create the new BizTalk message
var memoryStream = new MemoryStream();
memoryStream.Write(resourceXmlBytes, 0, resourceXmlBytes.Length);
memoryStream.Position = 0;
inmsg.BodyPart.Data = memoryStream;
As there is a 1:1 correlation between the FHIR ResourceType and xml root node name there is no need to have a configuration parameter for root node name/namespace as we have in the standard JSON decode component. Surely we could have some parameters controlling some aspects of the .NET API for HL7 FHIR but not for this simple proof-of-concept.
Lets see how the XML now looks after a HTTP POST of the source FHIR JSON to the same ReceiveLocation with a pipeline using our new pipeline component.
Great, we now have a correct FHIR XML instance and we can use it in a BizTalk integration process.
To return/send an instance of a FHIR message we just need to reverse the process by creating a FHIR JSON to FHIR XML BizTalk pipeline component and use that in a send pipeline.