0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

HL7 FHIR JP Core 仕様書の歩き方 - 最初の壁を越えるための最小ガイド

0
Posted at

はじめに

医療情報システムの相互運用性規格として注目される HL7 FHIR。日本では JAMI(日本医療情報学会)から JP Core 実装ガイドが公開されています。

しかし、いざ仕様書を開いてみると

  • ページが大量にあって、どこから読めばいいか分からない
  • プロファイル詳細の表が出てきても、何を意味するのか分からない
  • リンクをクリックしても、さらに別の表が出てきて迷子になる

必要があってFHIRを勉強しようと思いましたが完全に迷子です。本記事は、AIの力を借りて何をどう読めばよいかを、最小限の範囲で整理したものです。

対象読者:

  • FHIR/JP Core の存在は知っているが、仕様書を開いて挫折した人

取り扱う範囲:

  • 総合ガイダンス
  • Patient プロファイル(1つだけ)
  • REST API の基本的な GET/POST サンプル

全体を網羅することよりも、「次に自分で読み進められる足場」を作ることを目的にしています。


1. 結論: 最初に読むべき順番

仕様書全体は膨大ですが、初心者が最初に読むべきはこの順番です。

順番 ページ 所要時間の目安
1 総合ガイダンス 30分
2 JP_Patient プロファイル 1〜2時間
3 MustSupport と Cardinality 30分
4 欠損値の扱い 30分

とりあえずPatient を先に読むことができればいいでしょう。MustSupport/Cardinality は抽象的なルールなので、Patient で具体例に触れれば後の理解が深まります。


2. 総合ガイダンス: 30分で読み終わる前提知識

URL: https://jpfhir.jp/fhir/core/1.2.0-a/guide-general.html

ここは2つのセクションだけ読めば十分ではないかと思います。

2-1. JP Core の立ち位置

JP Core は、HL7 FHIR R4 をベースに、日本国内向けの最小限の適合性要件を定めたものです。重要な性質が3つあります:

  1. 「最小限」がキーワード: JP Core 自体の制約は緩い。各病院・ベンダーは JP Core から派生したプロファイルを作って、自社向けに厳格化することが想定されている
  2. HL7 v2.5 との後方互換性なし: 既存システムとの連携には変換層が必要
  3. JAMI の WG が策定: 日本HL7協会の正式承認は得ていない(自己責任で利用)

この性質は頭に入れておくいいと思います。

2-2. SHALL / SHOULD / MAY の定義

仕様書全体で使われるキーワードです。RFC 2119 準拠で厳密に定義されています。読み飛ばさず、必ず押さえておきます

キーワード 意味
SHALL 必ず実装しなければならない
SHALL NOT 実装してはならない
SHOULD 推奨(外す場合は熟慮必須)
SHOULD NOT 非推奨(採用する場合は熟慮必須)
MAY 任意(実装してもしなくてもよい)

これ以降のセクション(2.1.3 実装ガイド定義 / 2.1.4 機械翻訳文章 / 2.1.5 質問先 / 2.1.6 主体)は今は保留です。実装フェーズに入ってから必要な部分だけ参照でいいのではないでしょうか。

特に「IP Statements(知的財産権)」のリンクの羅列は索引(リファレンス)であり、通読する場所ではありません。「薬剤コードは何を使うんだっけ?」と思った時に開く辞書として使います。


3. Patient プロファイル: ここから本番

URL: https://jpfhir.jp/fhir/core/1.2.0-a/StructureDefinition-jp-patient.html

3-1. 「プロファイル詳細」とは何か

ページの中ほどに「プロファイル詳細」というセクションがあり、6つのタブがある表が現れます。これがつまずきポイントです。

プロファイル詳細の正体: 「このリソースを送受信する時の契約書 ≒ テーブル定義書」 です。

データベース設計者の感覚で読み替えると、こうなります:

FHIR 用語 DB 設計の用語
プロファイル詳細 テーブル定義書(CREATE TABLE文 + 制約)
Patient リソース テーブル(例: 患者テーブル)
各要素(name, gender 等) カラム
Cardinality(0..1 等) NULL許容 / NOT NULL
Type(string, code 等) データ型
Binding CHECK 制約 / 外部マスタ参照
Flags(?!, Σ, C) 特殊な制約や挙動のメモ

3-2. 6つのタブの使い分け

タブ 何が見える いつ使うか
Differential Table FHIR 標準からの差分だけ JP Core が標準から何を変えたか知りたい時
Key Elements Table 重要な要素だけ 全体像を素早く掴みたい時
Snapshot Table 全要素の完全な一覧 実装時に一番よく使う
Terminology Bindings コードセットのバインディング マスタ設計時
Constraints 追加の制約 バリデーション実装時
Statistics/References 統計情報 あまり使わない

とりあえず Snapshot Table だけ見ればOKだと思います。これが「テーブル定義」に相当します。

3-3. Cardinality の読み方

Snapshot Table に出てくる 0..1 1..* などの記法:

記法 意味 DB での例え
0..1 任意の単一値 NULL 許容カラム
1..1 必須の単一値 NOT NULL カラム
0..* 任意の複数値 0〜N 件の子テーブル
1..* 1件以上必須の複数値 1件以上必須の子テーブル

ただし、FHIR 特有の落とし穴があります:

最小 Cardinality が 1 であることは、要素が存在することのみを要求しており、例えば、その要素は DataAbsentReason 拡張のみを持つかもしれない

つまり 1..1 でも、「値不明(unknown)」を示す dataAbsentReason 拡張だけが入っているケースがあり得ます。RDB の NOT NULL 感覚で設計すると事故になります。業務上の必須チェックはアプリ層で別途実装する必要があります。

3-4. Flags の意味

Snapshot Table の Flags 列に出てくる記号:

記号 意味
?! is-modifier(これを無視すると意味が変わる要素。無視禁止)
Σ サマリ表示対象
C Constraint(追加制約あり)

特に ?! は重要で、active=false の患者を active 無視で「アクティブ」として扱うと重大事故になります。

3-5. 共通基盤項目とリソース固有項目

Snapshot Table の最初の方に出てくる以下の要素は、FHIR の全リソース共通の基盤項目です:

id / meta / implicitRules / language / text / contained / extension

これらは Patient 固有ではなく、Encounter でも Observation でも同じです。Patient で一度理解すれば、他のリソースでも同じです。

「Patient 固有の項目」は、identifier name gender birthDate address などスクロールした先に出てきます。ここが本番です。

3-6. 読む時の3つの問い

各要素について、以下を意識すると整理しやすいです:

  1. 自社システムのどのテーブルのどのカラムに対応するか
  2. データ型・制約は一致しているか。ズレている場合は変換が必要か
  3. この要素は連携で使うか、使わないか(例: religion は日本では使わないことが多い)

4. サンプルJSONとプロファイル定義の違い

JP Core サイトには Patient のサンプル JSON もあります:

URL: https://jpfhir.jp/fhir/core/1.2.0-a/Patient-jp-patient-example-1.json.html

サンプル JSON の例

{
  "resourceType": "Patient",
  "id": "jp-patient-example-1",
  "identifier": [{
    "system": "urn:oid:1.2.392.100495.20.3.51.11311011",
    "value": "00000010"
  }],
  "name": [{
    "use": "official",
    "text": "山田 太郎",
    "family": "山田",
    "given": ["太郎"]
  }],
  "gender": "male",
  "birthDate": "1990-05-10"
}

gender というキーに "male" という値が入っている。普通の JSON です。

補足:StructureDefinition XML

<element id="Patient.gender">
  <path value="Patient.gender"/>
  <min value="0"/>
  <max value="1"/>
  <type>
    <code value="code"/>
  </type>
</element>

→ これはメタデータ。「Patient.gender というパスの要素は、最小0個・最大1個、型は code 型」という定義そのものを表現する XML


5. FHIR サーバとのやり取り: 普通の REST API です

最後に「実際の通信」を見てみます。FHIR の本質はとてもシンプルで、HTTP メソッド + URL + JSON Body だけです。

5-1. URL の基本フォーマット

[ベースURL] / [リソースタイプ] / [リソースID] ? [検索条件]

例:

https://example-fhir.jp/fhir / Patient / jp-patient-example-1
        ↑ベースURL              ↑リソース  ↑リソースID

5-2. 5つの基本操作

FHIR 操作 HTTP メソッド + URL SQL での例え
Read(1件取得) GET /Patient/{id} SELECT * FROM patient WHERE id = ?
Search(検索) GET /Patient?name=山田 WHERE name LIKE '%山田%'
Create(新規) POST /Patient (Body: JSON) INSERT
Update(更新) PUT /Patient/{id} (Body: JSON) UPDATE
Delete(削除) DELETE /Patient/{id} DELETE

5-3. 実例: Read

GET https://example-fhir.jp/fhir/Patient/jp-patient-example-1
Accept: application/fhir+json

レスポンス:

HTTP/1.1 200 OK
Content-Type: application/fhir+json

{
  "resourceType": "Patient",
  "id": "jp-patient-example-1",
  "identifier": [{ "system": "urn:oid:...", "value": "00000010" }],
  "name": [{ "text": "山田 太郎", "family": "山田", "given": ["太郎"] }],
  "gender": "male",
  "birthDate": "1990-05-10"
}

5-4. 実例: Search

GET https://example-fhir.jp/fhir/Patient?name=山田

レスポンスは、**Bundle という「複数件結果ラッパー」**で返ります。これも FHIR リソースの1つ。

{
  "resourceType": "Bundle",
  "type": "searchset",
  "total": 2,
  "entry": [
    {
      "fullUrl": "https://example-fhir.jp/fhir/Patient/jp-patient-example-1",
      "resource": { "resourceType": "Patient", "id": "...", "name": [...] }
    },
    {
      "fullUrl": "https://example-fhir.jp/fhir/Patient/jp-patient-example-2",
      "resource": { "resourceType": "Patient", "id": "...", "name": [...] }
    }
  ]
}

検索パラメータは強力で、SQL を書かずに複雑な検索ができます:

GET /Patient?birthdate=ge1980-01-01&birthdate=le1989-12-31
GET /Patient?name=山田&gender=male
GET /Patient?_count=20&_offset=40

5-5. 実例: Create

POST https://example-fhir.jp/fhir/Patient
Content-Type: application/fhir+json

{
  "resourceType": "Patient",
  "identifier": [{ "system": "urn:oid:...", "value": "00000099" }],
  "name": [{ "text": "佐藤 花子", "family": "佐藤", "given": ["花子"] }],
  "gender": "female",
  "birthDate": "1985-03-15"
}

レスポンス:

HTTP/1.1 201 Created
Location: https://example-fhir.jp/fhir/Patient/12345

{
  "resourceType": "Patient",
  "id": "12345",
  "meta": {
    "versionId": "1",
    "lastUpdated": "2026-04-23T15:30:00+09:00"
  },
  "identifier": [{...}],
  "name": [{...}],
  "gender": "female",
  "birthDate": "1985-03-15"
}

POST で送った JSON に、サーバが idmeta を付けて返してくるのが特徴です。

5-6. ステータスコードとエラー

コード 意味
200 OK 取得・更新成功
201 Created 新規作成成功
400 Bad Request リクエスト JSON の形式エラー
404 Not Found リソースが存在しない
422 Unprocessable Entity プロファイル違反(必須項目欠損等)

エラー時は OperationOutcome という専用リソースが返ります:

{
  "resourceType": "OperationOutcome",
  "issue": [{
    "severity": "error",
    "code": "required",
    "diagnostics": "Patient.identifier is required (1..*)"
  }]
}

5-7. 公開テストサーバで実際に試せる

HAPI FHIR が無料で公開しているテストサーバがあります。ブラウザで開くだけで動きます:

このURLを叩いてみると、普通のREST APIで動くことがわかります。

まとめ

FHIR JP Core 仕様書の最初の壁を越えるための要点は以下の通りです:

  • 最初に読むのは「総合ガイダンス」と「Patient プロファイル」だけでOK
  • 総合ガイダンスは「JP Core の立ち位置」と「SHALL/SHOULD/MAY の定義」を押さえれば十分
  • プロファイル詳細は 「テーブル定義書」 と読み替える
  • Snapshot Table だけ見ればよく、idextension は共通基盤項目として読み飛ばせる
  • Cardinality は基本 NULL/NOT NULL と同じだが、1..1 でも dataAbsentReason で空が許される点に注意
  • FHIR API は普通の REST API。HTTP メソッド + URL + JSON Body

参考リンク

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?