FHIR平台應用程式開發 ==== 本文假設前提是除Bundle外,相關資料皆已匯入FHIR Server。以癌要事前審查為例,Bundle必須包含Claim及相關Profile。主要開發工具是[firely .NET SDK](https://docs.fire.ly/projects/Firely-NET-SDK/en/latest/)相關技術包含: * FHIR Client * FHIR Search / Bundle parsing * FHIRPath * FHIR Read * FHIR Model * FHIR Serialization 我們將工作分成三個步驟: 步驟一:取得FHIR Server Claim清單 --- 這個步驟的重點在透過FHIR Client連接FHIR Server,設定搜尋條件後,使用FHIR Search取得Claim的清單。還傳值以Bundle封裝,因此需解析Bundle的結構才能列相關資料。 ``` FhirClient client = new FhirClient("http://localhost:8080/fhir"); // Read all Claim resource from the server with a search query var searchParams = new SearchParams(); searchParams.Add("status", "active"); // read limit to 50 results searchParams.LimitTo(50); var bundle = await client.SearchAsync<Claim>(searchParams); foreach (var entry in bundle.Entry) { var claim = (Claim)entry.Resource; Console.WriteLine($"Claim ID: {claim.Id}, Status: {claim.Status}, Type: {claim.Type.Coding[0].Code}"); } ``` 步驟二:取得Claim所對應之Profile(Reference)清單 --- 使用FHIR Modle根據Resource id取得特定Claim Resource,同時使用FHIRPath語法,取的Claim相關Profile的Reference清單。這一段FHIRPath`descendants().where($this is Reference).reference`就是取得該Resource物件下,資料格式為Resource的Elemet,並回傳reference。 Claim所包含的Profile也有第二階的Reference,此時可應用相同技術,取的所有Bundle所需要之Reference清單。 ``` // Read a specific Claim by ID var claimId = "9f76d5a5-30c0-419a-9e32-9605a095de49"; // replace with actual Claim ID var specificClaim = await client.ReadAsync<Claim>($"Claim/{claimId}"); Console.WriteLine($"Specific Claim ID: {specificClaim.Id}, Status: {specificClaim.Status}, Type: {specificClaim.Type.Coding[0].Code}"); // using FHIR path to get all reference to Claim var directReferenceValues = specificClaim.Select("descendants().where($this is Reference).reference"); // Print the number of references found Console.WriteLine($"Number of direct references in Claim {specificClaim.Id}: {directReferenceValues.Count()}"); foreach (var refValue in directReferenceValues) { Console.WriteLine($"Direct Reference: {refValue}"); } ``` 步驟三:產生Bundle --- 首先,新增一個Bundle物件,並根據前一步驟所得的Reference清單,將Claim以及相關Profile,從FHIR Server讀取後加入Bundle.Entry。 產生Bundle後,可使用FHIR Serialization技術,將FHIR Bundle物件轉換為Json格式。 ``` // Create a Bundle to hold the Claim resources var claimBundle = new Bundle { Type = Bundle.BundleType.Collection, Timestamp = DateTimeOffset.Now, Id = Guid.NewGuid().ToString(), // Generate a new unique ID for the bundle Meta = new Meta { Profile = new List<string> { "https://nhicore.nhi.gov.tw/pas/StructureDefinition/Bundle-twpas" } }, Entry = new List<Bundle.EntryComponent>() }; // add specificClaim to the Bundle claimBundle.Entry.Add(new Bundle.EntryComponent { Resource = specificClaim, FullUrl = $"urn:uuid:{specificClaim.Id}" }); // add directReferenceValues to the Bundle as Reference resources foreach (var reference in directReferenceValues) { if (reference is Hl7.Fhir.Model.FhirString refString) { Bundle.EntryComponent entry = new Bundle.EntryComponent { Resource = await client.ReadAsync<Resource>(refString.Value), // Read the resource from the FHIR server FullUrl = $"urn:uuid:{refString.Value}" // Set the full URL to the reference ID }; claimBundle.Entry.Add(entry); // Add the entry to the bundle } } // Serialize the Bundle to JSON with pretty print var fhirJsonSerializer = new FhirJsonSerializer(new SerializerSettings { Pretty = true }); var bundleJson = fhirJsonSerializer.SerializeToString(claimBundle); // print the serialized JSON Console.WriteLine(bundleJson); ```