最稳妥方式是直接用fhirjsonserializer序列化fhir资源为json,需设置resourceformat.json、确保resourcetype已初始化,并注册自定义extension;xml反序列化须严格校验命名空间;json反序列化失败主因是版本不匹配或字段格式异常,应启用ignoreunknownelements等设置。

用 FhirJsonSerializer 序列化 FHIR 资源为 JSON
直接调用 FhirJsonSerializer 是最稳妥的方式,它内置了 FHIR 版本感知、类型映射和扩展处理逻辑。别自己用 JsonConvert.SerializeObject 硬转——FHIR 资源里大量使用 Element、BackboneElement 和动态 Extension,手动序列化会丢字段或格式错乱。
- 必须先设置
FhirJsonSerializerSettings的ResourceFormat为ResourceFormat.Json(默认就是,但显式写上更安全) - 确保资源实例的
ResourceType已正确初始化(比如new Patient()会自动设,但空构造后手动赋值Id不会触发) - 如果资源含自定义
Extension,需提前注册:调用FhirSerializationUtil.RegisterCustomElement<myextensiontype>()</myextensiontype> - 示例:
FhirJsonSerializer serializer = new FhirJsonSerializer(); string json = serializer.SerializeToString(patient);
用 FhirXmlSerializer 反序列化 XML 到 C# 对象
XML 反序列化比 JSON 更容易出错,主因是命名空间和元素顺序敏感。FHIR XML 必须带 xmlns="http://hl7.org/fhir",缺这个命名空间会导致 FhirXmlSerializer.Deserialize<patient>(xml)</patient> 返回 null 或抛 InvalidOperationException。
- 传入的 XML 字符串开头必须包含完整的根命名空间声明,不能只靠
<patient></patient>简写 - 不要用
XDocument.Load+ 手动提取再反序列化——FhirXmlSerializer内部依赖完整文档上下文 - 若 XML 来自外部系统且命名空间不规范(比如用了前缀
fhir:),先做预处理替换:把fhir:Patient→Patient,并补全默认命名空间 - 示例:
string xml = @"<Patient xmlns=""http://hl7.org/fhir""><id value=""123""/></Patient>"; FhirXmlSerializer xmlSer = new FhirXmlSerializer(); Patient p = xmlSer.Deserialize<Patient>(xml);
JSON 反序列化失败常见原因和绕过方法
最常见的报错是 Newtonsoft.Json.JsonSerializationException: Cannot create and populate list type Hl7.Fhir.Model.List`1,本质是 JSON 中某个数组字段类型不匹配(比如服务器返回了 "identifier": [],但 SDK 期望 "identifier": [{}])。
- 优先检查 FHIR 版本是否对齐:.NET SDK 的
Hl7.Fhir.R4包只能处理 R4 JSON,拿 STU3 的 JSON 去反序列化必崩 - 遇到未知字段(如服务端加了非标准扩展字段),在
FhirJsonSerializerSettings中启用IgnoreUnknownElements = true - 若 JSON 含时间字段格式不标准(如
"2023-10-05T14:30"缺少秒或时区),设置DateTimeStyle = DateTimeStyle.RoundTrip - 别 catch
JsonSerializationException后吞掉——它通常意味着数据结构损坏,应记录原始 JSON 用于排查
性能与线程安全注意事项
FhirJsonSerializer 和 FhirXmlSerializer 实例本身不是线程安全的,但可以复用。反复 new 它们不会显著拖慢,但没必要;而共享单例时要注意内部缓存状态。
- 推荐每线程一个实例,或用
static readonly声明(只要不修改其Settings属性) - 序列化大资源(如含数百个
Observation的Bundle)时,避免在 Web API action 中同步调用SerializeToString——改用SerializeToStreamAsync配合HttpResponse.Body - XML 序列化比 JSON 慢约 3–5 倍,仅在必须兼容旧系统时用;日常接口尽量走 JSON
- 如果频繁转换同一类资源(比如总在处理
Condition),可预先调用FhirSerializer.PrepareForType<condition>()</condition>加速首次序列化
实际用的时候,最容易被忽略的是 FHIR 版本绑定和命名空间校验——两个看似“应该能通”的文件,往往卡在这两处。多打一行日志输出 resource.ResourceType 和 xml.Contains("xmlns="),省掉半天排查。










