Daxia Blog
Uncategorized | Rust | WebUI | FHIR | Javascript | KB

FHIR Patch

FHIR Patch

背景介绍

在 HTTP 协议中,除了常见的请求方法GET、POST、PUT、DELETE,还有一些不常见的方法,例如:PATCH、HEAD等。它们各自具有不同的语义,有着不同的应用场景。我们今天要说的就是PATCH方法,用于部分更新,而非完整更新。在经过设计权衡之后还坚定的选择使用PATCH方法,无非就是基于性能和安全这两个业务场景。

PATCH 的工作原理是创建一个“补丁文档”,该文档指定客户端希望对资源进行的更改,并将其提交给服务器。然后,服务器将这些更改应用于指定的资源;或者,如果更改不合适,就拒绝更改。每个“补丁文档”要声明:

  • 要执行的动作(add、remove)
  • 资源中要执行动作的位置,也就是路径表达式。
  • 新值(要添加的,或者要更改的)

在标准方面,RFC 5261: XML Patch Operations Framework Utilizing XPath Selectors 提供了XML格式的补丁文档定义,而RFC 6902: JSON Patch提供了JSON格式的补丁文档定义。

FHIR中的Patch应用

拿来主义

所以在FHIR规范之初,采用拿来主义,沿用了已有的RFC定义的补丁操作标准,存在两种Patch方式:

  • JSON Patch
  • XML Patch

PATCH操作虽然是部分更新,但也是属于更新操作。所以,在FHIR资源的版本管理上,PATCH操作和PUT操作是一致的,都会导致版本的增加。

兼容性问题

这两种Patch方式其实是与FHIR规范不兼容的。为什么这么说呢?从设计理念来讲,FHIR规范的实现应该是格式无关的,也就是说,无论是采用XML还是JSON格式,都应不影响处理逻辑实现。但是在Patch操作上,因为两种不同的补丁文档格式标准采用的路径表达式的不同,造成在实现时要按照不同格式标准分别进行路径的解析。其中,XML Patch中使用了XPath规范,而JSON Patch中使用了JSON Pointer规范。这种不同导致了实现时要根据不同路径表达方式给出不同实现方法。

FHIRPath的出现

2019年,HL7 发布了FHIR STU3版本,FHIRPath 正式进入FHIR规范体系,并且达到了标准化程度。既然FHIRPath 统一了路径的表达方式,那么增加一种Patch方法也就理所应当,实现无关性也就水到渠成。

我认为,在FHIRPath Patch出现之后,以上两种Patch方式终将退出历史舞台,如同早期使用Atom格式来表示资源的集合,现在也已经被Bundle类型所代替。

FHIR Patch 示例

下面是使用了JSON Patch格式的示例:

  PATCH http://hapi.fhir.org/baseR5/Patient/95575
  Content-Type: application/json-patch+json; charset=UTF-8
  
  [{
  	"op": "add",
  	"path": "/birthDate",
  	"value": "2020-10-10"
  }]

下面是使用了XML Patch格式的示例:

  PATCH http://hapi.fhir.org/baseR5/Patient/95575
  Content-Type: application/xml-patch+xml; charset=UTF-8
  
  <patch xmlns:f="http://hl7.org/fhir">
      <remove sel="f:Patient/f:birthDate"/>
  </patch>

下面是使用了FHIRPath Patch格式的示例:

  PATCH http://hapi.fhir.org/baseR5/Patient/95575
  Content-Type: application/fhir+xml; charset=UTF-8
  
  <Parameters xmlns="http://hl7.org/fhir">
      <parameter>
          <name value="operation"/>
          <part>
              <name value="type"/>
              <valueCode value="replace"/>
          </part>
          <part>
              <name value="path"/>
              <valueString value="Patient.birthDate"/>
          </part>
          <part>
              <name value="value"/>
              <valueDate value="1930-01-01"/>
          </part>
      </parameter>x
  </Parameters>

从上面的示例可以看到,行11-14记录的就是路径,遵循着FHIRPath规范。 这时格式是XML和JSON已经无关紧要,都不会对路径解析产生影响,也就达到了实现无关性。

写在后面的话

其实在FHIR规范中,进行资源的部分更新,除了使用Patch方法之外,还有很多使用Operation的例子。例如:$meta-add$meta-delete。我认为如果使用Patch方法的主要因素是性能,那还可以。如果是基于安全考量,想得到更好的安全访问控制,那么我认为使用Operation方式才是最优解,因为可以在服务访问层级进行更细粒度访问权限的控制。

如果一定要使用FHIR的Patch方案,为了向后的兼容性,应尽量采用FHIRPath Patch方式。

About Daxia
我是一名独立开发者,国家工信部认证高级系统架构设计师,在健康信息化领域与许多组织合作。具备大型卫生信息化平台产品架构、设计和开发的能力,从事软件研发、服务咨询、解决方案、行业标准编著相关工作。
我对健康信息化非常感兴趣,尤其是与HL7和FHIR标准的健康互操作性。我是HL7中国委员会成员,从事FHIR培训讲师和FHIR测评现场指导。
我还是FHIR Chi的作者,这是一款用于FHIR测评的工具。