
医疗系统的接口设计HL7/FHIR 协议的数据交换规范一、深度引言与场景痛点为什么两个医院的系统不能直接传输病历在国内从一个医院转诊到另一个医院时最常发生的场景是病人拿着一叠纸质报告和 CT 胶片从一个楼走到另一个楼。为什么不能直接把数据传过去因为两个医院的 HIS医院信息系统来自不同的厂商使用的数据格式、编码方式和传输协议可能完全不同。这就是医疗信息互操作性问题。HL7Health Level 7和它的现代版本 FHIRFast Healthcare Interoperability Resources就是为了解决这个问题而设计的标准协议。理解这套协议对于开发医疗系统的后端工程师来说是必备知识。二、底层机制与原理深度剖析FHIR 的资源模型FHIR 的核心思想是把医疗数据建模为一系列标准化的资源Resource。所有资源都可以通过 RESTful API 访问。三、生产级代码实现与最佳实践# FHIR 资源模型 —— Patient 资源示例 from dataclasses import dataclass from typing import Optional import json dataclass class FHIRPatient: FHIR Patient 资源 遵循 FHIR R4 规范 https://www.hl7.org/fhir/patient.html resourceType: str Patient # 标识符可多个身份证号、病历号等 identifiers: list[dict] None # 姓名 family_name: str given_name: str # 性别: male | female | other | unknown gender: str unknown # 出生日期: YYYY-MM-DD birth_date: Optional[str] None # 联系电话 phone: Optional[str] None # 地址 address: Optional[str] None def to_fhir_json(self) - dict: 转换为 FHIR JSON 格式 FHIR 对 JSON 格式有严格的字段命名规范 必须遵循 PascalCase 和小驼峰混合命名。 resource { resourceType: Patient, id: self._generate_id(), identifier: self._format_identifiers(), name: [{ use: official, family: self.family_name, given: [self.given_name], }], gender: self.gender, } if self.birth_date: resource[birthDate] self.birth_date if self.phone: resource[telecom] [{ system: phone, value: self.phone, use: mobile, }] if self.address: resource[address] [{ text: self.address, }] return resource classmethod def from_fhir_json(cls, data: dict) - FHIRPatient: 从 FHIR JSON 解析为 Python 对象 name data.get(name, [{}])[0] telecom data.get(telecom, [{}]) address data.get(address, [{}]) return cls( family_namename.get(family, ), given_namename.get(given, [])[0] if name.get(given) else , genderdata.get(gender, unknown), birth_datedata.get(birthDate), phonetelecom[0].get(value) if telecom else None, addressaddress[0].get(text) if address else None, ) def _format_identifiers(self) - list[dict]: 格式化标识符列表 if not self.identifiers: return [] return [ { system: ident.get(system, ), value: ident.get(value, ), } for ident in self.identifiers ] def _generate_id(self) - str: 生成资源 ID import uuid return str(uuid.uuid4()) # Observation 资源 —— 实验室检查结果 class FHIRObservation: FHIR Observation 资源 —— 检查/检验结果 resourceType: str Observation def __init__(self, patient_id: str, code: str, value: float, unit: str, reference_range: str ): self.patient_id patient_id self.code code # LOINC 编码 self.value value # 测量值 self.unit unit # 单位 self.reference_range reference_range # 参考范围 def to_fhir_json(self) - dict: 转换为 FHIR Observation JSON 示例血糖 6.2 mmol/L return { resourceType: Observation, status: final, subject: { reference: fPatient/{self.patient_id} }, code: { coding: [{ system: http://loinc.org, code: self.code, display: self._get_loinc_display(self.code), }] }, valueQuantity: { value: self.value, unit: self.unit, system: http://unitsofmeasure.org, code: self.unit, }, referenceRange: [{ text: self.reference_range }] if self.reference_range else [], effectiveDateTime: datetime.now().isoformat(), } def _get_loinc_display(self, code: str) - str: LOINC 编码 → 中文名称 loinc_map { 2345-7: 血清葡萄糖, 26453-1: 红细胞计数, 26464-8: 白细胞计数, 777-3: 血小板计数, } return loinc_map.get(code, code)四、边界分析与架构权衡FHIR 的互操作性优势FHIR 相比旧版 HL7 v2/v3 的优势基于 RESTful 架构任何 Web 开发者都能快速上手使用 JSON/XML非医疗领域的工具链友好资源粒度合理如 Patient、Observation不会太粗也不会太细本地化的挑战FHIR 以欧美医疗体系为基础设计在国内落地的挑战ICD-10疾病编码与国内的 ICD-10-CM 有差异药品编码体系不同国内用 YPID中医诊断在 FHIR 中缺乏标准化支持国内实践中通常采用FHIR 框架 国内扩展的模式保持核心资源不变在扩展字段中增加本地化内容。五、总结HL7/FHIR 的价值在于它为医疗数据的交换提供了一套共同语言。就像 HTTP 让所有网站可以互通一样FHIR 让不同厂商的医疗系统能够互通。对于后端工程师来说即便不从事医疗行业FHIR 的设计理念也值得学习资源化建模把业务对象拆解为独立的、可组合的资源RESTful 风格用统一的 HTTP 动词操作资源可扩展性核心字段标准化扩展字段灵活化这种标准化核心 灵活扩展的设计模式适用于任何需要多系统互操作的场景。