Generating Go code from OpenAPI schemas

Turn OpenAPI schemas into clean, dependency-free Go models.

Generate formatted Go models from OpenAPI schemas. The default output uses only the Go standard library. Import github.com/pb33f/libopenapi/generator/golang.

For HTTP clients, see Generating SDKs. For interfaces and type aliases, see Generating TypeScript.

Rendering a whole component map

Save your spec as openapi.yaml. This writes its component schemas to models.gen.go:

package main

import (
    "fmt"
    "os"

    "github.com/pb33f/libopenapi"
    "github.com/pb33f/libopenapi/generator/golang"
)

func main() {
    source, err := os.ReadFile("openapi.yaml")
    if err != nil {
        panic(err)
    }
    doc, err := libopenapi.NewDocument(source)
    if err != nil {
        panic(err)
    }
    model, err := doc.BuildV3Model()
    if err != nil {
        panic(err)
    }
    if model.Model.Components == nil {
        panic("the document has no components")
    }
    file, err := golang.NewGenerator().RenderSchemas(model.Model.Components.Schemas)
    if err != nil {
        panic(err)
    }
    for _, d := range file.Diagnostics {
        fmt.Printf("[%s] %s: %s\n", d.Code, d.Path, d.Message)
    }
    if err := os.WriteFile("models.gen.go", file.Source, 0o644); err != nil {
        panic(err)
    }
}

Rendering a single schema

golang.RenderSchema("Product", proxy) accepts a *base.SchemaProxy and returns source bytes. Use RenderSchemas for a component map with references between models.

What you get back

RenderSchemas returns a *GeneratedFile with Source, PackageName, Types, and Diagnostics. The optional SchemaMetadata sidecar supports round trips.

How OpenAPI shapes map to Go

Schema Go
Object with properties Struct.
Array []T.
String / integer / number / boolean string / int / float64 / bool.
Optional property Pointer with omitempty.
Nullable Pointer.
Scalar enum Named type; constants are optional.
Unambiguous discriminated oneOf Typed union and JSON wrapper.
Ambiguous oneOf / anyOf json.RawMessage wrapper.

Inline objects get named types. String formats stay strings unless configured; numeric formats such as int64 and float select sized Go types.

Shaping the output

Pass options to golang.RenderSchema or golang.NewGenerator:

Option Effect
WithPackageName(name) Package name; default models.
WithGeneratedComment(true) Generated-code header.
WithEnumConstants(true) Typed enum constants.
WithOptionalFieldsAsPointers(false) Optional fields become values.
WithGenerateYAMLTags(true) YAML tags alongside JSON tags.
WithFormatMapping(format, goType, importPath) Custom string-format type.
WithTypeNameResolver(fn) Custom names.
WithSchemaMetadataSidecar(true) Round-trip metadata.

Diagnostics

Inspect Code, Path, and Message for lossy or notable decisions. Validation constraints such as minimum and pattern are not enforced by generated models.

Typed unions

A discriminator or shared required const can select a concrete variant during JSON decoding. Ambiguous compositions keep the payload as raw JSON.

Enums as constants

WithEnumConstants(true) emits a typed constant for each scalar enum value.

Round-tripping unknown fields

Schema-valued additionalProperties collects extra keys in an AdditionalProperties map. Generated JSON methods preserve them through decode/encode. Use WithAdditionalPropertiesMethods(false) to supply your own methods.

Going the other way

Parsing Code covers Go → OpenAPI and the metadata sidecar for faithful round trips.