- Notifications
You must be signed in to change notification settings - Fork108
OpenAPI v3 code generator for go
License
ogen-go/ogen
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
OpenAPI v3 Code Generator for Go.
go get -d github.com/ogen-go/ogen
//go:generate go run github.com/ogen-go/ogen/cmd/ogen --target target/dir -package api --clean schema.json
or using container:
docker run --rm \ --volume".:/workspace" \ ghcr.io/ogen-go/ogen:latest --target workspace/petstore --clean workspace/petstore.yml
- No reflection or
interface{}
- The json encoding is code-generated, optimized and usesgo-faster/jx for speed and overcoming
encoding/json
limitations - Validation is code-generated according to spec
- The json encoding is code-generated, optimized and usesgo-faster/jx for speed and overcoming
- Code-generated static radix router
- No more boilerplate
- Structures are generated from OpenAPI v3 specification
- Arguments, headers, url queries are parsed according to specification into structures
- String formats like
uuid
,date
,date-time
,uri
are represented by go types directly
- Statically typed client and server
- Convenient support for optional, nullable and optional nullable fields
- No more pointers
- Generated Optional[T], Nullable[T] or OptionalNullable[T] wrappers with helpers
- Special case for array handling with
nil
semantics relevant to specification- When array is optional,
nil
denotes absence of value - When nullable,
nil
denotes that value isnil
- When required,
nil
currently the same as[]
, but is actually invalid - If both nullable and required, wrapper will be generated (TODO)
- When array is optional,
- Generated sum types for oneOf
- Primitive types (
string
,number
) are detected by type - Discriminator field is used if defined in schema
- Type is inferred by unique fields if possible
- Primitive types (
- Extra Go struct field tags in the generated types
- OpenTelemetry tracing and metrics
Example generated structure from schema:
// Pet describes #/components/schemas/Pet.typePetstruct {Birthday time.Time`json:"birthday"`Friends []Pet`json:"friends"`IDint64`json:"id"`IP net.IP`json:"ip"`IPV4 net.IP`json:"ip_v4"`IPV6 net.IP`json:"ip_v6"`KindPetKind`json:"kind"`Namestring`json:"name"`NextOptData`json:"next"`NicknameNilString`json:"nickname"`NullStrOptNilString`json:"nullStr"`Rate time.Duration`json:"rate"`TagOptUUID`json:"tag"`TestArray1 [][]string`json:"testArray1"`TestDateOptTime`json:"testDate"`TestDateTimeOptTime`json:"testDateTime"`TestDurationOptDuration`json:"testDuration"`TestFloat1OptFloat64`json:"testFloat1"`TestInteger1OptInt`json:"testInteger1"`TestTimeOptTime`json:"testTime"`TypeOptPetType`json:"type"`URI url.URL`json:"uri"`UniqueID uuid.UUID`json:"unique_id"`}
Example generated server interface:
// Server handles operations described by OpenAPI v3 specification.typeServerinterface {PetGetByName(ctx context.Context,paramsPetGetByNameParams) (Pet,error)// ...}
Example generated client method signature:
typePetGetByNameParamsstruct {Namestring}// GET /pet/{name}func (c*Client)PetGetByName(ctx context.Context,paramsPetGetByNameParams) (resPet,errerror)
Instead of using pointers,ogen
generates generic wrappers.
For example,OptNilString
isstring
that is optional (no value) and can benull
.
// OptNilString is optional nullable string.typeOptNilStringstruct {ValuestringSetboolNullbool}
Multiple convenience helper methods and functions are generated, some of them:
func (OptNilString)Get() (vstring,okbool)func (OptNilString)IsNull()boolfunc (OptNilString)IsSet()boolfuncNewOptNilString(vstring)OptNilString
Ifogen
encounters recursive types that can't be expressed in go, pointers are used as fallback.
ForoneOf
sum-types are generated.ID
that is one of[string, integer]
will be represented like that:
typeIDstruct {TypeIDTypeStringstringIntint}// Also, some helpers:funcNewStringID(vstring)IDfuncNewIntID(vint)ID
OpenAPI enablesSpecification Extensions,which are implemented as patterned fields that are always prefixed byx-
.
Optionally, server name can be specified byx-ogen-server-name
, for example:
{"openapi":"3.0.3","servers": [ {"x-ogen-server-name":"production","url":"https://{region}.example.com/{val}/v1", }, {"x-ogen-server-name":"prefix","url":"/{val}/v1", }, {"x-ogen-server-name":"const","url":"https://cdn.example.com/v1" } ],(...)
Optionally, type name can be specified byx-ogen-name
, for example:
{"$schema":"http://json-schema.org/draft-04/schema#","type":"object","x-ogen-name":"Name","properties": {"foobar": {"$ref":"#/$defs/FooBar" } },"$defs": {"FooBar": {"x-ogen-name":"FooBar","type":"object","properties": {"foo": {"type":"string" } } } }}
Optionally, type name can be specified byx-ogen-properties
, for example:
components:schemas:Node:type:objectproperties:parent:$ref:"#/components/schemas/Node"child:$ref:"#/components/schemas/Node"x-ogen-properties:parent:name:"Prev"child:name:"Next"
The generated source code looks like:
// Ref: #/components/schemas/NodetypeNodestruct {Prev*Node`json:"parent"`Next*Node`json:"child"`}
Optionally, additional Go struct field tags can be specified byx-oapi-codegen-extra-tags
, for example:
components:schemas:Pet:type:objectrequired: -idproperties:id:type:integerformat:int64x-oapi-codegen-extra-tags:gorm:primaryKeyvalid:customIdValidator
The generated source code looks like:
// Ref: #/components/schemas/PettypePetstruct {IDint64`gorm:"primaryKey" valid:"customNameValidator" json:"id"`}
By default, ogen loads the entire JSON body into memory before decoding it.Optionally, streaming JSON encoding can be enabled byx-ogen-json-streaming
, for example:
requestBody:required:truecontent:application/json:x-ogen-json-streaming:trueschema:type:arrayitems:type:number
Optionally, operations can be grouped so a handler interface will be generated for each group of operations.This is useful for organizing operations for large APIs.
The group for operations on a path or individual operations can be specified byx-ogen-operation-group
, for example:
paths:/images:x-ogen-operation-group:Imagesget:operationId:listImages.../images/{imageID}:x-ogen-operation-group:Imagesget:operationId:getImageByID.../users:x-ogen-operation-group:Usersget:operationId:listUsers...
The generated handler interfaces look like this:
// x-ogen-operation-group: ImagestypeImagesHandlerinterface {ListImages(ctx context.Context,req*ListImagesRequest) (*ListImagesResponse,error)GetImageByID(ctx context.Context,req*GetImagesByIDRequest) (*GetImagesByIDResponse,error)}// x-ogen-operation-group: UserstypeUsersHandlerinterface {ListUsers(ctx context.Context,req*ListUsersRequest) (*ListUsersResponse,error)}typeHandlerinterface {ImagesHandlerUsersHandler// All un-grouped operations will be on this interface}
Code generation provides very efficient and flexible encoding and decoding of json:
// Decode decodes Error from json.func (s*Error)Decode(d*jx.Decoder)error {ifs==nil {returnerrors.New("invalid: unable to decode Error to nil")}returnd.ObjBytes(func(d*jx.Decoder,k []byte)error {switchstring(k) {case"code":iferr:=func()error {v,err:=d.Int64()s.Code=int64(v)iferr!=nil {returnerr}returnnil}();err!=nil {returnerrors.Wrap(err,"decode field\"code\"")}case"message":iferr:=func()error {v,err:=d.Str()s.Message=string(v)iferr!=nil {returnerr}returnnil}();err!=nil {returnerrors.Wrap(err,"decode field\"message\"")}default:returnd.Skip()}returnnil})}
About
OpenAPI v3 code generator for go