OpenAPIでoneOfやanyOfを使うのは避けるべき
ツールのサポートが不十分な上、言語やツールによって扱いが異なるため、おすすめしない。
以前から避けた方が良いという話は知っていたが、今回、外部サービスのスキーマからコードを生成する際に遭遇して嫌な思いをしたので書いた。
OpenAPI Generatorで以前から報告されている
OpenAPI Generatorの次のIssueでは、2021年からoneOf
やanyOf
、allOf
のサポートが不十分であると報告されている。
https://github.com/OpenAPITools/openapi-generator/issues/10514
言語毎に異なる問題が報告されており、混沌としている。
これはOpenAPI Generatorだけの問題ではなく、他のコード生成ツールでも少なからずoneOf
やanyOf
を利用した場合の問題が報告されている。OpenAPI Generatorで報告が多く、対応が遅れているように見える一因には、他のツールに比べて多くの言語をサポートしていることがあるだろう。
言語やツールによって扱いが異なる
oneOf
やanyOf
はOpenAPIの仕様としては統一されているが、サポートが不十分であることや言語の仕様により生成されるコードが、言語やツールによって異なる振る舞いをする可能性が多分にある。
有名な例では、TypeScriptでoneOf
がXORではなくORであるUnion型で生成される問題などがある。
自社サービス内で利用するだけであれば恐らく問題はないが、外部にスキーマを提供して他の開発者が利用する場合、このような差分は混乱を招く可能性がある。
ツールの問題がなくても避けるべき
今回、私が遭遇した外部サービスのスキーマでは、APIのレスポンスが配列かオブジェクトのどちらかを返すようにoneOf
が利用されていた。
しかも問題なのは、実際は空オブジェクトや空配列を返す場合あるということで、oneOf
はオブジェクトの場合、定義されたプロパティが存在しないと本来バリデーションエラーになるため、実際の挙動を満たせないコードが生成されていた。
この外部サービスの開発現場では、オブジェクトまたは配列のようなレスポンスを返せていることから、比較的型の緩い言語が利用されており、生成されているコードでエラーが発生しないのではないかと思われる。
このようなケースでは、ツールの問題がなくとも言語によっては表現することが非常に困難である。
サービスを外部に公開するような場合では、oneOf
やanyOf
が必要になってしまうようなAPI設計を避けてほしいものだ。