Gousset, the Go Usable Semi-static Schema Extractor Tool, is a tool designed to extract OpenAPI specs from Go data structures.
To generate an OpenAPI spec, call openapi.FromImplementation as follows:
import "github.com/pasqal-io/gousset/openapi"
import "github.com/pasqal-io/gousset/openapi/operation"
import "github.com/pasqal-io/gousset/openapi/path"
import "github.com/pasqal-io/gousset/openapi/response"
import "github.com/pasqal-io/gousset/shared"
spec, err := openapi.FromImplementation(openapi.Implementation {
Info: openapi.Info {
// Fill in the metadata for your API, explaining what it's for,
// who to contact for assistance, etc.
// ...
},
Endpoints: []path.Implementation {
{
Path: "/api/v1/user/{id}",
Summary: "Operations on an individual user",
PerVerb: map[Verb]operation.Impleementation {
path.Get: {
Summary: "Get the information on the user",
Response: response.Implementation {
Default: response.ResponseImplementation {
Description: "In case of success",
Contents: &map[string]media.Implementation {
"application/json": {
Example: &MyUser {
Name: "John Doe",
},
},
},
},
},
}
},
}
},
})This is a bit heavy, but if your code or framework is sufficiently high-level, you should be able to extract the information automatically from the code.
Use tags json, query, path, header to rename go-style UpperCamelCased fields into
their corresponding public names.
Use tag flatten to flatten a struct or a map into its container, e.g.
type User struct {
Name string `json:"name"`
Email string `json:"email"`
}
type MyArguments struct {
User User `flatten:""`
}to document this as if this were the following struct
type MyArguments struct {
Name string `json:"name"`
Email string `json:"email"`
}This is useful when you share User between several structs. This works also through maps
and interfaces.
gousset recognizes the following tags that you may use to document individual parameters:
Use tag description to explain the parameter. This may use markdown.
type MyArguments struct {
Arg Type `description:"some description"`
}Use tag format on a string or number to restrain the parameter to some format, e.g.
type MyArguments struct {
Email string `format:"email"`
}See also HasFormat for an alternative method if you use a type Email string instead of
a raw string.
See gousset.openapi.schema.Format* constants for a list of weel-known formats.
Use tag deprecated on a field to mark it as deprecated.
Use tag example on a string to provide an example of its value.
See also HasExample and HasExamples to generalize this to an entire type.
Use tag pattern to restrict a string field to some regex.
Use tags minimum:"number", maximum:"number", exclusiveMinimum:"number",
exclusiveMaximum:"number" to restrict the values of numbers.
Use maxItems:"number", minItems:"number" to restrict the length of arrays.
Use maxLength:"number", minLength:"number" to restrict the length of strings.
Use maxProperties:"number", minProperties:"number" to restrict the number of
properties of a map.
You can also customize entire types.
Sum types (e.g. int | string) are very different between Go and OpenSpec.
In Go, se represent the sum type as a struct, e.g.
type MyFooOrBar struct {
Foo* Foo `variant:"variant_1" json:"foo"`
Bar* Bar `variant:"variant_2" json:"bar"`
}This will be compiled as if we had defined
type MyFooOrBar = {Foo* Foo} | {Bar* Bar}Alternatively, you can request flattening
type MyFooOrBar struct {
Foo* Foo `variant:"variant_1" json:"foo" flatten:""`
Bar* Bar `variant:"variant_2" json:"bar" flatten:""`
}This will be compiled as if we had defined
type MyFooOrBar = Foo | BarAs of this writing, this mechanism only works if Foo or Bar are struct. If you
need it to work with other types, don't hesitate to file an issue!
See all the interfaces in hooks to see how to document entire types.