如何将Firely C#返回的FHIR JSON解析为自定义eReferral对象
解决Firely C#客户端解析FHIR JSON提取指定字段的问题
首先定义自定义的eReferral类示例:
public class eReferral { public string ReferralReference { get; set; } public string Priority { get; set; } public string Specialty { get; set; } public string PatientId { get; set; } public string PatientName { get; set; } // 可选,根据需求添加 }
方案一:使用FhirJsonNode正确定位字段
如果坚持使用FhirJsonNode,核心注意点是FHIR扩展字段必须通过完整URL匹配,而非仅字段名。假设你的FHIR响应是Bundle(批量转诊)或单个ReferralRequest资源,代码如下:
using Hl7.Fhir.Serialization; string fhirJson = "你的FHIR JSON响应字符串"; var rootNode = FhirJsonNode.Parse(fhirJson); var referrals = new List<eReferral>(); // 处理Bundle类型响应 if (rootNode["resourceType"].ToString() == "Bundle") { foreach (var entryNode in rootNode["entry"].Elements()) { var resourceNode = entryNode["resource"]; if (resourceNode["resourceType"].ToString() != "ReferralRequest") continue; var eRef = new eReferral(); // 提取转诊引用(优先取fullUrl,无则取资源ID) eRef.ReferralReference = entryNode["fullUrl"]?.ToString() ?? resourceNode["id"].ToString(); // 提取患者信息(subject字段是Reference类型) var subjectNode = resourceNode["subject"]; if (subjectNode != null && !string.IsNullOrEmpty(subjectNode["reference"]?.ToString())) { eRef.PatientId = subjectNode["reference"].ToString().Split('/').Last(); // 若Bundle包含Patient资源,可在此解析患者名称 } // 提取Priority扩展(替换为你的实际扩展URL) var priorityExt = resourceNode["extension"]? .Elements() .FirstOrDefault(e => e["url"].ToString() == "http://your-institution.com/fhir/extension/referral-priority"); if (priorityExt != null) { // 假设priority是Code类型,根据实际类型调整(如valueString) eRef.Priority = priorityExt["valueCode"]?.ToString(); } // 提取Specialty扩展(替换为你的实际扩展URL) var specialtyExt = resourceNode["extension"]? .Elements() .FirstOrDefault(e => e["url"].ToString() == "http://your-institution.com/fhir/extension/referral-specialty"); if (specialtyExt != null) { // 假设specialty是CodeableConcept类型,取第一个coding的display eRef.Specialty = specialtyExt["valueCodeableConcept"]?["coding"]?.Elements().First()["display"]?.ToString(); } referrals.Add(eRef); } } // 处理单个ReferralRequest资源 else if (rootNode["resourceType"].ToString() == "ReferralRequest") { var eRef = new eReferral(); eRef.ReferralReference = rootNode["id"].ToString(); // 提取患者信息 var subjectNode = rootNode["subject"]; if (subjectNode != null) { eRef.PatientId = subjectNode["reference"].ToString().Split('/').Last(); } // 提取Priority扩展 var priorityExt = rootNode["extension"]? .Elements() .FirstOrDefault(e => e["url"].ToString() == "你的priority扩展URL"); if (priorityExt != null) { eRef.Priority = priorityExt["valueCode"]?.ToString(); } // 提取Specialty扩展 var specialtyExt = rootNode["extension"]? .Elements() .FirstOrDefault(e => e["url"].ToString() == "你的specialty扩展URL"); if (specialtyExt != null) { eRef.Specialty = specialtyExt["valueCodeableConcept"]?["coding"]?.Elements().First()["display"]?.ToString(); } referrals.Add(eRef); }
关键注意事项
- 扩展URL必须完全匹配:FHIR的扩展通过唯一URL标识,不能仅用"priority"或"specialty"作为匹配条件,必须使用响应中实际的完整URL。
- 字段类型匹配:根据FHIR响应中字段的实际类型调整取值(比如
priority可能是valueCode或valueString,specialty可能是valueCodeableConcept)。 - 空值判断:所有字段都要加null检查,避免空引用异常。
方案二:使用Firely强类型模型(推荐)
Firely提供了FHIR资源的强类型类,无需手动操作JSON节点,代码更简洁且不易出错。
首先安装对应FHIR版本的NuGet包(如R4版本):
Install-Package Hl7.Fhir.R4
然后编写解析代码:
using Hl7.Fhir.Model; using Hl7.Fhir.Serialization; string fhirJson = "你的FHIR JSON响应字符串"; var parser = new FhirJsonParser(); Bundle bundle = parser.Parse<Bundle>(fhirJson); var referrals = new List<eReferral>(); foreach (var entry in bundle.Entry) { if (entry.Resource is ReferralRequest referralRequest) { var eRef = new eReferral(); // 提取转诊引用 eRef.ReferralReference = entry.FullUrl ?? referralRequest.Id; // 提取患者信息 if (referralRequest.Subject != null && !string.IsNullOrEmpty(referralRequest.Subject.Reference)) { eRef.PatientId = referralRequest.Subject.Reference.Split('/').Last(); // 若Bundle包含Patient资源,直接查找解析患者名称 var patientEntry = bundle.Entry.FirstOrDefault(e => e.Resource is Patient && e.Resource.Id == eRef.PatientId); if (patientEntry?.Resource is Patient patient) { eRef.PatientName = patient.Name.FirstOrDefault()?.Text; } } // 提取Priority扩展 var priorityExt = referralRequest.Extension.FirstOrDefault(e => e.Url == "你的priority扩展URL"); if (priorityExt != null && priorityExt.Value is Code priorityCode) { eRef.Priority = priorityCode.Value; } // 提取Specialty扩展 var specialtyExt = referralRequest.Extension.FirstOrDefault(e => e.Url == "你的specialty扩展URL"); if (specialtyExt != null && specialtyExt.Value is CodeableConcept specialtyCc) { eRef.Specialty = specialtyCc.Coding.FirstOrDefault()?.Display; } referrals.Add(eRef); } }
强类型方案优势
- 编译时类型检查,避免手动写JSON路径的错误
- 直接利用Firely封装的FHIR资源类和扩展处理逻辑,代码更简洁
- 自动处理FHIR复杂类型(如
CodeableConcept、Reference)的解析
内容的提问来源于stack exchange,提问作者Richard Housham
相关产品推荐
相关产品推荐

