本記事はGo2 Advent Calendar の20日目の記事です。昨日はyaegashiさんによる、jsonx.go でした。

皆さんはOpenAPI Specification というモノをご存じでしょうか。OpenAPI SpecificationはJSONまたはYAMLでREST APIを表現するための仕様で、現在バージョン3.0.2 が最新です。いわゆるSwagger の後継で、バージョン1系、2系がSwagger、3系以降がOpenAPI、ということになっています(Swaggerなら聞いたことがある/使っているという人も多いのではないでしょうか)。

OpenAPI Specificationは人間にも機械にも(比較的)読みやすい仕様書として、コード生成や、ドキュメントページの生成に使用することが可能です。

個人的には専らコード生成に使用しており、Go言語向けの実装としてgithub.com/nasa9084/go-openapi (以下go-openapi)を実装・公開しています。 go-openapiは2017年ごろから細々と実装を続けており、(多分)二番目か三番目には古いと思われるOpenAPIのGo実装です。

基本的にはただひたすらOpenAPIのオブジェクトをGoの構造体として定義、値のバリデーション関数を用意しているといったもので、特別な機能はほとんどありません。 YAMLのパーサも、go-yaml/yaml を使用しており、自前では実装していません。

そんな中、@goccy さんが、encoding/jsonとコンパチなインターフェースを持ったYAMLパーサを開発した、という話を耳にし、これを機に、とgo-openapiの実装を一から書き直し始めました。 もともと、パースは完全にgo-yaml/yamlに依存しており、Unmarshal系のメソッドも実装していなかった(途中から全部書くのはつらかったので・・・)ため、一部バリデーションに必要な関数を埋め込んだりもできなかったので、書き直したいとは思っていたのです。

現時点ではまだマージしておらず 、書いている途中なのですが、大きな変更点として次の様なものがあります。

  • もともとパブリックだったフィールドをすべてプライベートに変更し、ゲッターをはやした
  • 各構造体に対応するUnmarshalYAML()メソッドをすべてコード生成するようにした
  • YAMLパーサはgithub.com/goccy/go-yaml に乗り換えた
  • rootオブジェクトを各構造体に埋め込むことで、バリデーションをとりやすくした

今後はよりコード生成に便利なメソッドを追加していきたいと思っています。

時間の都合で今日はここまで。技術的な話が全然無い記事になってしまった・・・