github.com/swaggest/openapi-goを使うとGoのコードからOpenAPIの定義(json/yaml)を生成できる。
pkg.go.dev
例:
package main
import (
"encoding/json"
"fmt"
"log"
openapi "github.com/swaggest/openapi-go"
"github.com/swaggest/openapi-go/openapi3"
)
type endpoint struct {
id string
method string
path string
request any
responses []response
}
type response struct {
status int
body any
}
func main() {
r := openapi3.Reflector{
Spec: &openapi3.Spec{
Openapi: "3.0.3",
Components: &openapi3.Components{},
},
}
r.Spec.Info.
WithTitle("Foo API").
WithDescription("Foo API Document.").
WithVersion("1.0")
list := []endpoint{
{
id: "PostFoo",
method: "POST",
path: "/foo",
request: new(PostFooRequest),
responses: []response{
{status: 201, body: new(Foo)},
{status: 400, body: new(ErrorResponse)},
},
},
{
id: "GetFoo",
method: "GET",
path: "/foo/{id}",
request: new(GetFooRequest),
responses: []response{
{status: 200, body: new(Foo)},
{status: 404, body: new(ErrorResponse)},
},
},
}
for _, v := range list {
oc, err := r.NewOperationContext(v.method, v.path)
if err != nil {
log.Println(err)
continue
}
oc.SetID(v.id)
oc.AddReqStructure(v.request)
for _, resp := range v.responses {
oc.AddRespStructure(resp.body, openapi.WithHTTPStatus(resp.status))
}
if err := r.AddOperation(oc); err != nil {
log.Println(err)
continue
}
}
b, err := json.MarshalIndent(r.Spec, "", " ")
if err != nil {
log.Println(err)
return
}
fmt.Println(string(b))
}
type PostFooRequest struct {
Data string `json:"data"`
}
type GetFooRequest struct {
ID string `json:"id" path:"id"`
}
type Foo struct {
ID string `json:"id"`
Data string `json:"data"`
}
type ErrorResponse struct {
Code string `json:"code"`
Message string `json:"message"`
}
list
の中身を既存コードから生成すれば途中からでも比較的簡単にOpenAPIを始められる。