OpenAPIにおけるnullとundefinedの設計
OpenAPIにおけるundefinedとnullの設計 | フューチャー技術ブログ
読んだ。
nullとundefinedに関してはこのサイトでも何度か悩んでる話を書いたし未だにどっちがいいのかよく分かってないので、リーディングリストから引っ張ってきて読みました。
今回はOpenAPIにおける話だけど、APIとのやり取りにおいては特にフロントエンド側でJavaScript(TypeScript)を使うことがほとんどで、そうなるとほぼ確実にnullとundefinedのどちらも扱うことになるし、あまりOpenAPIだからという視点では読んでいない。
undefined
OpenAPIの仕様において、リクエスト/レスポンスのデータ型を定義するSchema Objectのプロパティの1つであるrequiredが指定されていない状態を指します。
requiredとして指定されたプロパティはキーとしてインスタンスに含まれなければならないことを意味します。
Vueのコンポーネントのpropsの定義とかでも似たような感じだけど、required
を指定しない場合は「そもそもプロパティが存在しない(定義されていない)」 = defineされていない = undefinedということなんだろう。
required
は「そのキーが存在することが必須」ということであり、required
ではないということは「そのキーが存在しなくてもよい」ということ。
なので記事にもある通り、{ "id": null }
は、プロパティは存在するがnull型が許容されていないので(nullが許容されていなければ)invalidということになる。
requiredとはキー自体の必須・非必須を定義するプロパティであり、キーの具体的な値については関与していない
null
リクエスト/レスポンスにおけるプロパティの値としてのnullを指しています。
JSONの仕様として null型というのは明確に定義されています。
「プロパティがあるかどうか」ではなく「プロパティの値」のこと。
undefindeはキー、nullはプロパティ。
undefinedとnull
undefinde派の意見は、
- リクエスト/レスポンスのペイロードサイズを小さくするためにnull値は利用しない方が良い。
- 必要なプロパティのみが含まれている方が視認性が良い。
なるほど。
GoogleのJSON Style Guideでは、明確にnull値が必要となる場合以外は、プロパティ自体含めない形が推奨(ここでいうundefined派)されています。
たしかにペイロードのサイズが減るのは大事だな……。
対してnull派は、
- データの構造の全量を把握できるため、null値を含めた方が良い。
これも分かる。
integerやbooleanはnullableでないと空値相当(stringの空文字など)の表現ができない。
PATCHで差分更新をリクエストする場合、nullを許容していないと更新できない。たしかに。
となるとnot requiredの値を定義する場合はnullableにしておかないと差分更新ができない(できないわけじゃないけど)ということになる。
記事内のscoreの例だと、0への更新はできるけどnullへの更新はnullableじゃないとできない。
また、記事内のemailの例では、nullでもundefinedでもinvalidなメールアドレスののフィルターは機能しているので、むしろ空値の表現を空文字で行わないことのほうが大事になる。
個人的には、emailが必須な値の場合はnullableにして、「あとで設定するというステータス」を表現するためにnullが入ることを許容し、必須でない値の場合にはundefinedで「そもそもemailを持たないというステータス」を表現するのがよさそうかなと思う。
そもそもフロントエンドでnullとundefinedをどう使い分けるかを考えていたけど、フロントエンドだけで閉じてることではないなというのを再認識した。
基本的に「undefinedはキー、nullは値」を意識して使っていこう。