Skip to content
GameFabricPublic

About

openapi provides a framework for generating OpenAPI v3 specifications, using a chi mux, from code.

Topics

Resources

Stars

4 stars

Watchers

3 watching

Forks

Repository files navigation

OpenAPI Specification Generator

openapi provides a framework for generating OpenAPI v3 specifications, using a chi mux, from code. It attaches as one or more middleware to describe each route, removing itself at runtime to have no performance impact.

Usage

Struct Generator

oapi-gen is a struct function generator used to create documentation and attriubutes from struct field comments.

Any struct with the directive openapi:gen will have a documentation function generated.

Install

$ go install github.com/gamefabric/openapi/cmd/oapi-gen@<version>

A simple way to keep the generation up-to-date is to use Go's generation framework on each package that needs documentation functions.

//go:generate oapi-gen

Then run:

go generate ./...

Example

Running oapi-gen on the following package:

package somepackage

// TestObject is a test object.
//
//openapi:docs
type TestObject struct {
	// A is an example field.
	A string `json:"a"`

	// B is another example field.
	//
	//openapi:required
	//openapi:format=ipv4
	B string
}

Will produce a documentation file zz_generated.docs.go with the content:

package somepackage

// Code generated by oapi-docgen. DO NOT EDIT.

// Docs returns a set of property descriptions per property.
func (TestObject) Docs() map[string]string {
	return map[string]string{
		"B": "B is another example field.",
		"a": "A is an example field.",
	}
}

// Attributes returns a set of property attributes per property.
func (TestObject) Attributes() map[string]string {
	return map[string]string{
		"B": "required",
	}
}

// Formats returns a set of property formats per property.
func (TestObject) Formats() map[string]string {
	return map[string]string{
		"B": "ipv4",
	}
}

The following directives can be used on struct fields:

  • openapi:required: Marks the field as required.
  • openapi:readonly: Marks the field as read only.
  • openapi:format=<FORMAT>: Sets the format of the field, e.g. "date" or "ipv4". See list of valid formats.
  • openapi:enum=1,2,3: Sets the allowed enum values for this field. For array fields, this is applied to the item values (items.enum).

More Options

oapi-gen command supports the following additional arguments.

Options:
  -all
    	Parse all structs.
  -path string
    	The path to parse for documentation. Defaults to the current working directory.
  -q	Suppress generation output.
  -tag string
    	The tag to override the documentation key. (default "json")

Schema Customization

Types can control how their schema is generated by implementing any of the following methods. The generated documentation functions above implement several of these for you.

Method Effect
OpenAPISchemaType() []string Sets the schema type, for types with a custom JSON representation.
OpenAPISchemaFormat() string Sets the schema format, for types with a custom JSON representation.
OpenAPIV3OneOfTypes() []string Sets the schema to a oneOf of the given types.
Example() any Sets the schema example.
AllowedKeys() []string Restricts the keys of a map type (propertyNames, OpenAPI 3.1 only).
OpenAPIContext() map[string]any Provides context to the Transform methods of types nested within it.
Transform(ctx map[string]any, schema *kin.Schema) Makes final adjustments to the type's own schema.

Transforming Nested Types

A type that customizes how a nested type renders in JSON, and so cannot change its OpenAPI representation directly, can do so using OpenAPIContext and Transform. The outer type publishes values through OpenAPIContext, and the nested type reads them in Transform. This works no matter how deeply the nested type appears in the outer type.

// Outer renders Inner differently depending on its mode.
type Outer struct {
	Items []Middle `json:"items"`
}

func (Outer) OpenAPIContext() map[string]any {
	return map[string]any{"inner-mode": "compact"}
}

type Middle struct {
	Inner Inner `json:"inner"`
}

type Inner struct {
	Name string `json:"name"`
}

func (Inner) Transform(ctx map[string]any, schema *kin.Schema) {
	if ctx["inner-mode"] == "compact" {
		schema.Description = "Compact representation."
	}
}

Things to be aware of:

  • A type's context is collected before the schemas of its fields are generated, so it is visible to all nested types.
  • The context is shared by the whole spec build. Keys from different types are merged, with later types overwriting earlier ones, so use distinctive keys.
  • Transform runs after all other customizations for the type, so it can override them.

About

openapi provides a framework for generating OpenAPI v3 specifications, using a chi mux, from code.

Topics

Resources

Stars

4 stars

Watchers

3 watching

Forks

Releases

Used by

Contributors

Languages