3. 编码系统与标识符工程

在FHIR中,编码系统不是“一个字段填个码”那么简单。任何一个 Coding 都由三要素构成:system(系统标识,通常是URI)、code(该系统内的码值)、display(人类可读显示名)。其中 system 是工程上最容易出错、也最需要统一治理的部分。本节聚焦五类高频系统——SNOMED CT、LOINC、ICD-10、RxNorm、UCUM——讲清它们的标识、版本、URI策略,以及在FHIR资源中的具体表达方式。

一、system 到底填什么:URI 是“系统身份”,不是“版本号”

FHIR规范要求 Coding.system 使用URI形式,且该URI标识的是“编码系统本身”,而不是某一次发布的版本。版本信息应放在 Coding.version 中。这是初学者最常见的混淆点:把版本号拼进 system,会导致同一系统在不同版本下产生多个“伪系统”,破坏术语映射与校验。

以SNOMED CT为例,其国际版系统URI为:

http://snomed.info/sct

如果要指定某个国家版本或某个具体版本,FHIR推荐使用“模块化URI”方式,把版本信息编码进URI路径,而不是塞进 version 字段之外的地方。例如指定2024年1月国际版:

http://snomed.info/sct/900000000000207008/version/20240131

其中 900000000000207008 是SNOMED CT国际版的模块标识。这种“基础URI + 模块 + 版本”的写法,是SNOMED CT在FHIR中最规范的表达策略。

二、五大系统的标识与URI策略对照

下表给出本节五个系统的标准 system 值、版本表达方式与典型码值示例。注意:ICD-10在不同国家有不同变体(如ICD-10-CM),其URI必须区分,不能混用。

系统标准 system(URI)版本表达码值示例
SNOMED CThttp://snomed.info/sctURI路径或 version 字段73211009(糖尿病)
LOINChttp://loinc.orgversion 字段,如 2.772339-0(血糖)
ICD-10http://hl7.org/fhir/sid/icd-10version 字段E11(2型糖尿病)
ICD-10-CMhttp://hl7.org/fhir/sid/icd-10-cmversion 字段E11.9
RxNormhttp://www.nlm.nih.gov/research/umls/rxnormversion 字段860975(二甲双胍)
UCUMhttp://unitsofmeasure.org通常不标版本mg/dL、mmol/L

这里有一个关键工程约定:UCUM 的 system 是固定的,码值就是单位表达式本身,如 mg/dL。UCUM 是“单位语法系统”,不是“枚举码表”,因此它的 code 是大小写敏感的,mg 与 Mg 含义不同(后者是兆克)。在FHIR的 Quantity 中,单位必须用UCUM表达,才能被跨系统正确解析。

三、在FHIR资源中的表达:CodeableConcept 与 Coding 的层级关系

FHIR中绝大多数“编码型”字段使用 CodeableConcept。它的结构是:一个 CodeableConcept 包含 0..* 个 Coding,外加一个 text。这意味着同一个临床概念可以同时携带多个系统的编码,例如一个“2型糖尿病”诊断,可以同时给出SNOMED CT码和ICD-10码,供不同接收方按需取用。

下面是一个真实的FHIR JSON片段,展示同一概念的多系统编码:

{
  "coding": [
    {
      "system": "http://snomed.info/sct",
      "code": "44054006",
      "display": "Diabetes mellitus type 2"
    },
    {
      "system": "http://hl7.org/fhir/sid/icd-10",
      "code": "E11",
      "display": "Type 2 diabetes mellitus"
    }
  ],
  "text": "2型糖尿病"
}

注意:text 是兜底显示,不能替代编码。工程上应保证至少一个 Coding 的 system 与 code 组合是有效的,否则接收方无法做术语校验。

四、版本治理:为什么 version 不能省

编码系统会持续更新:LOINC每年两次大版本,SNOMED CT每月国际版发布,ICD-10各国修订节奏不同。如果 Coding.version 缺失,接收方无法判断该码值是在哪个版本下有效的,可能导致“码值存在但语义已变更”的静默错误。

推荐策略是:在数据交换中,凡是涉及临床决策或计费的编码,必须带 version。对于UCUM,由于其语法稳定,通常可省略版本;对于SNOMED CT,若使用模块化URI,版本已隐含在URI中,version 字段可留空,但需在系统层面统一约定,避免同一系统两种写法混用。

工程建议:建立一份“系统URI注册表”,把每个编码系统的标准URI、版本字段名、是否大小写敏感、是否允许本地扩展等属性固化下来,作为接口开发和数据校验的唯一依据。任何新增系统都必须先注册,再使用。

五、URI策略的常见陷阱与校验方法

实际项目中最常见的三类错误:一是把版本号写进 system,如 http://loinc.org/2.77;二是ICD-10与ICD-10-CM混用同一URI;三是UCUM单位写成非标准形式,如 mg/dl(应为 mg/dL)。

校验方法可以分三步:第一步,用正则或白名单校验 system 是否属于已注册URI集合;第二步,校验 code 是否符合该系统的基本格式(如LOINC为数字-数字,UCUM为合法单位表达式);第三步,若带 version,校验 version 是否在允许的版本列表中。这三步可以在FHIR验证器或接口网关中实现。

FHIR 编码系统标识与版本治理关系图 CodeableConcept 临床概念容器 Coding #1 system / code / display version(可选) Coding #2 system / code / display version(可选) text 兜底显示,不可替代编码 同一概念可携带多系统编码 供不同接收方按需取用 解析 已注册编码系统(system URI 白名单) SNOMED CT http://snomed.info/sct | 模块化URI可带版本 | 码值:73211009 LOINC http://loinc.org | version 字段标版本 | 码值:2339-0 ICD-10 / ICD-10-CM http://hl7.org/fhir/sid/icd-10(-cm) | 变体必须区分URI | 码值:E11 RxNorm http://www.nlm.nih.gov/research/umls/rxnorm | 码值:860975 UCUM http://unitsofmeasure.org | 码值即单位表达式,大小写敏感 | mg/dL 校验三步:① system 白名单 ② code 格式 ③ version 有效性

把这张图当作接口评审时的对照卡:左侧是FHIR数据结构的层级,右侧是必须注册的系统URI清单,底部是校验顺序。只要 system 不在白名单、code 格式不符、version 不在允许列表,就应在入库前拦截,而不是等到下游消费时才暴露问题。

六、本地扩展与映射的边界

当标准系统无法覆盖本地概念时,FHIR允许使用本地编码系统,但URI必须使用机构自有域名,例如 http://example.org/fhir/CodeSystem/local-lab。本地码不能伪装成标准系统码,也不能把本地码直接塞进SNOMED CT的system下。正确做法是:本地码单独成系统,再通过 ConceptMap 建立与标准系统的映射关系,映射结果标注等价程度(equivalent、wider、narrower等)。

总结本节要点:system 是系统身份,不是版本;version 是版本治理的关键字段;UCUM 的 code 是大小写敏感的单位表达式;多系统编码通过 CodeableConcept 的多个 Coding 并行表达;本地扩展必须独立URI并走 ConceptMap 映射。把这四条落到接口契约和校验规则里,术语集成的稳定性就有了基础。