OpenAPI Extensions
July 12, 2026 ยท View on GitHub
As well as the core OpenAPI support, oapi-codegen also supports the following OpenAPI extensions, as denoted by the OpenAPI Specification Extensions.
x-go-type / x-go-type-import
Override the generated type definition (and optionally, add an import from another package).
Using the x-go-type (and optionally, x-go-type-import when you need to import another package) allows overriding the type that oapi-codegen determined the generated type should be.
We can see this at play with the following schemas:
components:
schemas:
Client:
type: object
required:
- name
properties:
name:
type: string
id:
type: number
ClientWithExtension:
type: object
required:
- name
properties:
name:
type: string
# this is a bit of a contrived example, as you could instead use
# `format: uuid` but it explains how you'd do this when there may be
# a clash, for instance if you already had a `uuid` package that was
# being imported, or ...
x-go-type: googleuuid.UUID
x-go-type-import:
path: github.com/google/uuid
name: googleuuid
id:
type: number
# ... this is also a bit of a contrived example, as you could use
# `type: integer` but in the case that you know better than what
# oapi-codegen is generating, like so:
x-go-type: int64
From here, we now get two different models:
// Client defines model for Client.
type Client struct {
Id *float32 `json:"id,omitempty"`
Name string `json:"name"`
}
// ClientWithExtension defines model for ClientWithExtension.
type ClientWithExtension struct {
Id *int64 `json:"id,omitempty"`
Name googleuuid.UUID `json:"name"`
}
You can see this in more detail in the example code.
x-go-type-skip-optional-pointer
Do not add a pointer type for optional fields in structs.
Tip
If you prefer this behaviour, and prefer to not have to annotate your whole OpenAPI spec for this behaviour, you can use output-options.prefer-skip-optional-pointer=true to default this behaviour for all fields.
It is then possible to override this on a per-type/per-field basis where necessary.
By default, oapi-codegen will generate a pointer for optional fields.
Using the x-go-type-skip-optional-pointer extension allows omitting that pointer.
We can see this at play with the following schemas:
components:
schemas:
Client:
type: object
required:
- name
properties:
name:
type: string
id:
type: number
ClientWithExtension:
type: object
required:
- name
properties:
name:
type: string
id:
type: number
x-go-type-skip-optional-pointer: true
From here, we now get two different models:
// Client defines model for Client.
type Client struct {
Id *float32 `json:"id,omitempty"`
Name string `json:"name"`
}
// ClientWithExtension defines model for ClientWithExtension.
type ClientWithExtension struct {
Id float32 `json:"id,omitempty"`
Name string `json:"name"`
}
You can see this in more detail in the example code.
x-go-name
Override the generated name of a field or a type.
By default, oapi-codegen will attempt to generate the name of fields and types in as best a way it can.
However, sometimes, the name doesn't quite fit what your codebase standards are, or the intent of the field, so you can override it with x-go-name.
We can see this at play with the following schemas:
openapi: "3.0.0"
info:
version: 1.0.0
title: x-go-name
components:
schemas:
Client:
type: object
required:
- name
properties:
name:
type: string
id:
type: number
ClientWithExtension:
type: object
# can be used on a type
x-go-name: ClientRenamedByExtension
required:
- name
properties:
name:
type: string
id:
type: number
# or on a field
x-go-name: AccountIdentifier
From here, we now get two different models:
// Client defines model for Client.
type Client struct {
Id *float32 `json:"id,omitempty"`
Name string `json:"name"`
}
// ClientRenamedByExtension defines model for ClientWithExtension.
type ClientRenamedByExtension struct {
AccountIdentifier *float32 `json:"id,omitempty"`
Name string `json:"name"`
}
You can see this in more detail in the example code.
x-go-type-name
Override the generated name of a type.
Note
Notice that this is subtly different to the x-go-name, which also applies to fields within structs.
By default, oapi-codegen will attempt to generate the name of types in as best a way it can.
However, sometimes, the name doesn't quite fit what your codebase standards are, or the intent of the field, so you can override it with x-go-name.
We can see this at play with the following schemas:
openapi: "3.0.0"
info:
version: 1.0.0
title: x-go-type-name
components:
schemas:
Client:
type: object
required:
- name
properties:
name:
type: string
id:
type: number
ClientWithExtension:
type: object
x-go-type-name: ClientRenamedByExtension
required:
- name
properties:
name:
type: string
id:
type: number
# NOTE attempting a `x-go-type-name` here is a no-op, as we're not producing a _type_ only a _field_
x-go-type-name: ThisWillNotBeUsed
From here, we now get two different models and a type alias:
// Client defines model for Client.
type Client struct {
Id *float32 `json:"id,omitempty"`
Name string `json:"name"`
}
// ClientWithExtension defines model for ClientWithExtension.
type ClientWithExtension = ClientRenamedByExtension
// ClientRenamedByExtension defines model for ClientWithExtension.
type ClientRenamedByExtension struct {
Id *float32 `json:"id,omitempty"`
Name string `json:"name"`
}
You can see this in more detail in the example code.
x-omitempty
Force the presence of the JSON tag omitempty on a field.
In a case that you may want to add the JSON struct tag omitempty to types that don't have one generated by default - for instance a required field - you can use the x-omitempty extension.
We can see this at play with the following schemas:
openapi: "3.0.0"
info:
version: 1.0.0
title: x-omitempty
components:
schemas:
Client:
type: object
required:
- name
properties:
name:
type: string
id:
type: number
ClientWithExtension:
type: object
required:
- name
properties:
name:
type: string
# for some reason, you may want this behaviour, even though it's a required field
x-omitempty: true
id:
type: number
From here, we now get two different models:
// Client defines model for Client.
type Client struct {
Id *float32 `json:"id,omitempty"`
Name string `json:"name"`
}
// ClientWithExtension defines model for ClientWithExtension.
type ClientWithExtension struct {
Id *float32 `json:"id,omitempty"`
Name string `json:"name,omitempty"`
}
You can see this in more detail in the example code.
x-omitzero
Force the presence of the JSON tag omitzero on a field.
Note
omitzero was added in Go 1.24. If you're not using Go 1.24 in your project, this won't work.
In a case that you may want to add the JSON struct tag omitzero to types, you can use the x-omitzero extension.
We can see this at play with the following schemas:
openapi: "3.0.0"
info:
version: 1.0.0
title: x-omitzero
components:
schemas:
Client:
type: object
required:
- name
properties:
name:
type: string
id:
type: number
ClientWithExtension:
type: object
required:
- name
properties:
name:
type: string
id:
type: number
x-omitzero: true
From here, we now get two different models:
// Client defines model for Client.
type Client struct {
Id *float32 `json:"id,omitempty"`
Name string `json:"name"`
}
// ClientWithExtension defines model for ClientWithExtension.
type ClientWithExtension struct {
Id *float32 `json:"id,omitempty,omitzero"`
Name string `json:"name"`
}
You can see this in more detail in the example code.
x-go-json-ignore
When (un)marshaling JSON, ignore field(s).
By default, oapi-codegen will generate json:"..." struct tags for all fields in a struct, so JSON (un)marshaling works.
However, sometimes, you want to omit fields, which can be done with the x-go-json-ignore extension.
We can see this at play with the following schemas:
openapi: "3.0.0"
info:
version: 1.0.0
title: x-go-json-ignore
components:
schemas:
Client:
type: object
required:
- name
properties:
name:
type: string
complexField:
type: object
properties:
name:
type: string
accountName:
type: string
# ...
ClientWithExtension:
type: object
required:
- name
properties:
name:
type: string
complexField:
type: object
properties:
name:
type: string
accountName:
type: string
# ...
x-go-json-ignore: true
From here, we now get two different models:
// Client defines model for Client.
type Client struct {
ComplexField *struct {
AccountName *string `json:"accountName,omitempty"`
Name *string `json:"name,omitempty"`
} `json:"complexField,omitempty"`
Name string `json:"name"`
}
// ClientWithExtension defines model for ClientWithExtension.
type ClientWithExtension struct {
ComplexField *struct {
AccountName *string `json:"accountName,omitempty"`
Name *string `json:"name,omitempty"`
} `json:"-"`
Name string `json:"name"`
}
Notice that the ComplexField is still generated in full, but the type will then be ignored with JSON marshalling.
You can see this in more detail in the example code.
x-oapi-codegen-extra-tags
Generate arbitrary struct tags to fields.
If you're making use of a field's struct tags to i.e. apply validation, decide whether something should be logged, etc, you can use x-oapi-codegen-extra-tags to set additional tags for your generated types.
We can see this at play with the following schemas:
openapi: "3.0.0"
info:
version: 1.0.0
title: x-oapi-codegen-extra-tags
components:
schemas:
Client:
type: object
required:
- name
- id
properties:
name:
type: string
id:
type: number
ClientWithExtension:
type: object
required:
- name
- id
properties:
name:
type: string
id:
type: number
x-oapi-codegen-extra-tags:
validate: "required,min=1,max=256"
safe-to-log: "true"
gorm: primarykey
From here, we now get two different models:
// Client defines model for Client.
type Client struct {
Id float32 `json:"id"`
Name string `json:"name"`
}
// ClientWithExtension defines model for ClientWithExtension.
type ClientWithExtension struct {
Id float32 `gorm:"primarykey" json:"id" safe-to-log:"true" validate:"required,min=1,max=256"`
Name string `json:"name"`
}
You can see this in more detail in the example code.
x-enum-varnames / x-enumNames
Override generated variable names for enum constants.
When consuming an enum value from an external system, the name may not produce a nice variable name. Using the x-enum-varnames extension allows overriding the name of the generated variable names.
We can see this at play with the following schemas:
openapi: "3.0.0"
info:
version: 1.0.0
title: x-enumNames and x-enum-varnames
components:
schemas:
ClientType:
type: string
enum:
- ACT
- EXP
ClientTypeWithNamesExtension:
type: string
enum:
- ACT
- EXP
x-enumNames:
- Active
- Expired
ClientTypeWithVarNamesExtension:
type: string
enum:
- ACT
- EXP
x-enum-varnames:
- Active
- Expired
From here, we now get two different forms of the same enum definition.
// Defines values for ClientType.
const (
ACT ClientType = "ACT"
EXP ClientType = "EXP"
)
// Defines values for ClientTypeWithNamesExtension.
const (
ClientTypeWithNamesExtensionActive ClientTypeWithNamesExtension = "ACT"
ClientTypeWithNamesExtensionExpired ClientTypeWithNamesExtension = "EXP"
)
// Defines values for ClientTypeWithVarNamesExtension.
const (
ClientTypeWithVarNamesExtensionActive ClientTypeWithVarNamesExtension = "ACT"
ClientTypeWithVarNamesExtensionExpired ClientTypeWithVarNamesExtension = "EXP"
)
// ClientType defines model for ClientType.
type ClientType string
// ClientTypeWithNamesExtension defines model for ClientTypeWithNamesExtension.
type ClientTypeWithNamesExtension string
// ClientTypeWithVarNamesExtension defines model for ClientTypeWithVarNamesExtension.
type ClientTypeWithVarNamesExtension string
You can see this in more detail in the example code.
x-deprecated-reason
Add a GoDoc deprecation warning to a type.
When an OpenAPI type is deprecated, a deprecation warning can be added in the GoDoc using x-deprecated-reason.
We can see this at play with the following schemas:
openapi: "3.0.0"
info:
version: 1.0.0
title: x-deprecated-reason
components:
schemas:
Client:
type: object
required:
- name
properties:
name:
type: string
id:
type: number
ClientWithExtension:
type: object
required:
- name
properties:
name:
type: string
deprecated: true
x-deprecated-reason: Don't use because reasons
id:
type: number
# NOTE that this doesn't generate, as no `deprecated: true` is set
x-deprecated-reason: NOTE you shouldn't see this, as you've not deprecated this field
From here, we now get two different forms of the same enum definition.
// Client defines model for Client.
type Client struct {
Id *float32 `json:"id,omitempty"`
Name string `json:"name"`
}
// ClientWithExtension defines model for ClientWithExtension.
type ClientWithExtension struct {
Id *float32 `json:"id,omitempty"`
// Deprecated: Don't use because reasons
Name string `json:"name"`
}
Notice that because we've not set deprecated: true to the name field, it doesn't generate a deprecation warning.
You can see this in more detail in the example code.
x-order
Explicitly order struct fields.
Whether you like certain fields being ordered before others, or you want to perform more efficient packing of your structs, the x-order extension is here for you.
Note that x-order is 1-indexed - x-order: 0 is not a valid value.
We can see this at play with the following schemas:
openapi: "3.0.0"
info:
version: 1.0.0
title: x-order
components:
schemas:
Client:
type: object
required:
- name
properties:
a_name:
type: string
id:
type: number
ClientWithExtension:
type: object
required:
- name
properties:
a_name:
type: string
x-order: 2
id:
type: number
x-order: 1
From here, we now get two different forms of the same type definition.
// Client defines model for Client.
type Client struct {
AName *string `json:"a_name,omitempty"`
Id *float32 `json:"id,omitempty"`
}
// ClientWithExtension defines model for ClientWithExtension.
type ClientWithExtension struct {
Id *float32 `json:"id,omitempty"`
AName *string `json:"a_name,omitempty"`
}
You can see this in more detail in the example code.
x-oapi-codegen-only-honour-go-name
Only honour the x-go-name when generating field names.
Warning
Using this option may lead to cases where oapi-codegen's rewriting of field names to prevent clashes with other types, or to prevent including characters that may not be valid Go field names.
In some cases, you may not want use the inbuilt options for converting an OpenAPI field name to a Go field name, such as the name-normalizer: "ToCamelCaseWithInitialisms", and instead trust the name that you've defined for the type better.
In this case, you can use x-oapi-codegen-only-honour-go-name to enforce this, alongside specifying the allow-unexported-struct-field-names compatibility option.
This allows you to take a spec such as:
openapi: "3.0.0"
info:
version: 1.0.0
title: x-oapi-codegen-only-honour-go-name
components:
schemas:
TypeWithUnexportedField:
description: A struct will be output where one of the fields is not exported
properties:
name:
type: string
id:
type: string
# NOTE that there is an explicit usage of a lowercase character
x-go-name: accountIdentifier
x-oapi-codegen-extra-tags:
json: "-"
x-oapi-codegen-only-honour-go-name: true
And we'll generate:
// TypeWithUnexportedField A struct will be output where one of the fields is not exported
type TypeWithUnexportedField struct {
accountIdentifier *string `json:"-"`
Name *string `json:"name,omitempty"`
}
You can see this in more detail in the example code.