OpenAPI において $ref で参照したスキーマに対し参照元で nullable などのキーワードをマージする
TL;DR
-
$ref
と同じレベルにnullable
などのキーワードを配置することはできない。 -
$ref
でスキーマを共有しつつ、それを利用する側で場合に応じてnullable: true
などのキーワードを適用したい場合、allOf: [...]
を利用できる。
例)
# 参照先の定義内容をそのまま利用する場合:
hoge:
$ref: '#/components/schemas/HogeEnum'
# 参照先の定義内容に `nullable: true` を付け加える場合:
# ❌ これはできない ($ref と同じレベルにキーワードの指定ができない)
hoge:
nullable: true
$ref: '#/components/schemas/HogeEnum'
# ✅ これであれば OK $ref で参照したスキーマに nullable: true がマージされる
hoge:
nullable: true
allOf:
- $ref: '#/components/schemas/HogeEnum'
# 共有されるコンポーネント
components:
schemas:
HogeEnum:
type: string
description: なんらかのEnum
enum:
- hoge
- fuga
- piyo
前提
- OpenAPI 3.0 ベースでの話です
$ref でスキーマを共有する場合の問題点
OpenAPI では $ref
を使用することでスキーマの再利用性が向上しますが、柔軟性が低下する場合があります。
それは、$ref
と同列に他のキーワードを使用することができないという制約によるものです。
たとえば $ref
で参照されるスキーマが場合によって制約 ( nullable
など ) を加えたい場合です。
これの問題点に対処するため、allOf
を活用することが有効です。後続の節では、allOf
を使ってこの $ref
の制約を克服する方法について具体的に解説します。
allOf
を利用して制約を突破する
allOf
は、複数のスキーマを組み合わせて新たなスキーマを作成するためのキーワードです。allOf
を使うことで、参照されるスキーマのプロパティや制約を継承しつつ、個別に追加の制約やプロパティを設定することが可能です。
allOf
を利用したスキーマの合成については以下を参照してください。
Inheritance and Polymorphism
記事冒頭に掲載したコードを抜粋して解説してみます。
たとえば API 定義全体で共有したい以下のスキーマがあるとします。
# 共有されるコンポーネント
components:
schemas:
HogeEnum:
type: string
description: なんらかのEnum
enum:
- hoge
- fuga
- piyo
通常、この定義内容をそのまま利用する場合は以下のようになります。
# 参照先の定義内容をそのまま利用する場合
hoge:
$ref: '#/components/schemas/HogeEnum'
しかし、特定のケースでは nullable: true
としたいケースがあったりします。 ( たとえば POST では値が必須だけど PATCH/PUT の場合は null
以外を更新対象としたい場合など )
そのような場合は以下のように allOf
の配下に $ref
を置きます。 allOf
には配下の定義を1つにまとめて展開する効果があります。それによって、 allOf
の中で参照した $ref
の内容と allOf
と並列に記述された nullable: true
が合成されます。
# 参照先の定義内容に `nullable: true` を付け加える場合
hoge:
nullable: true
allOf:
- $ref: '#/components/schemas/HogeEnum'
まとめ
この記事では $ref
でスキーマを共有しつつ、特定のケースでは共有したスキーマに手を加たい場合に allOf
で $ref
の制約を回避する方法を示しました。
もし、この記事で示した方法以外により良い方法があるのでしたらコメントなどで教えてもらえると助かります。
Discussion