Schema Generation
5 minute read
Learn how the package automatically converts Go types to OpenAPI schemas.
Overview
The package uses reflection to convert Go types into OpenAPI schemas. This eliminates the need to manually define schemas in the specification.
Supported Go Types
Primitive Types
| Go Type | OpenAPI Type | OpenAPI Format |
|---|---|---|
string | string | - |
bool | boolean | - |
int, int32 | integer | int32 |
int64 | integer | int64 |
uint, uint32 | integer | int32 |
uint64 | integer | int64 |
float32 | number | float |
float64 | number | double |
byte | string | byte |
String Types
type User struct {
Name string `json:"name"`
Email string `json:"email"`
}
Generates:
type: object
properties:
name:
type: string
email:
type: string
Integer Types
type Product struct {
ID int `json:"id"`
Quantity int32 `json:"quantity"`
Stock int64 `json:"stock"`
}
Generates:
type: object
properties:
id:
type: integer
format: int32
quantity:
type: integer
format: int32
stock:
type: integer
format: int64
Floating-Point Types
type Product struct {
Price float64 `json:"price"`
Weight float32 `json:"weight"`
}
Generates:
type: object
properties:
price:
type: number
format: double
weight:
type: number
format: float
Boolean Types
type User struct {
Active bool `json:"active"`
Verified bool `json:"verified"`
}
Generates:
type: object
properties:
active:
type: boolean
verified:
type: boolean
Pointer Types
Pointer types are nullable and optional:
type User struct {
Name string `json:"name"`
Age *int `json:"age,omitempty"`
Email *string `json:"email,omitempty"`
}
In OpenAPI 3.1.x, pointers generate nullable: true. In OpenAPI 3.0.x, they’re optional fields.
Slices and Arrays
Slices become OpenAPI arrays:
type User struct {
Tags []string `json:"tags"`
Scores []int `json:"scores"`
Posts []Post `json:"posts"`
}
Generates:
type: object
properties:
tags:
type: array
items:
type: string
scores:
type: array
items:
type: integer
posts:
type: array
items:
$ref: '#/components/schemas/Post'
Maps
Maps become OpenAPI objects with additionalProperties:
type User struct {
Metadata map[string]string `json:"metadata"`
Scores map[string]int `json:"scores"`
}
Generates:
type: object
properties:
metadata:
type: object
additionalProperties:
type: string
scores:
type: object
additionalProperties:
type: integer
Nested Structs
Nested structs are converted to nested schemas or references:
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Address Address `json:"address"`
}
type Address struct {
Street string `json:"street"`
City string `json:"city"`
ZipCode string `json:"zip_code"`
}
Generates component schemas with references:
components:
schemas:
User:
type: object
properties:
id:
type: integer
name:
type: string
address:
$ref: '#/components/schemas/Address'
Address:
type: object
properties:
street:
type: string
city:
type: string
zip_code:
type: string
Embedded Structs
Embedded struct fields are flattened into the parent:
type Timestamps struct {
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Timestamps
}
Generates:
type: object
properties:
id:
type: integer
name:
type: string
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
Time Types
time.Time becomes a string with date-time format:
type User struct {
CreatedAt time.Time `json:"created_at"`
UpdatedAt *time.Time `json:"updated_at,omitempty"`
}
Generates:
type: object
properties:
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
JSON Tags
The package respects json struct tags:
type User struct {
ID int `json:"id"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Internal string `json:"-"` // Ignored
Optional string `json:"opt,omitempty"` // Optional
}
json:"name"- Sets the property namejson:"-"- Field is ignoredjson:",omitempty"- Field is optional (not required)
Schema Naming
Component schema names use the format pkgname.TypeName to prevent collisions:
// In package "api"
type User struct { ... } // Becomes "api.User"
// In package "models"
type User struct { ... } // Becomes "models.User"
This prevents naming collisions when the same type name exists in different packages.
Custom Schema Names
If you need custom schema names, use the openapi struct tag:
type User struct {
ID int `json:"id" openapi:"name=CustomUser"`
Name string `json:"name"`
}
Validation Tags
Validation tags affect the OpenAPI schema:
type CreateUserRequest struct {
Name string `json:"name" validate:"required"`
Email string `json:"email" validate:"required,email"`
Age int `json:"age" validate:"min=0,max=150"`
}
required- Adds field torequiredarraymin/max- Setsminimum/maximumfor numbersemail- Setsformat: emailfor strings
Documentation Tags
Use doc and example tags to enhance schemas:
type User struct {
ID int `json:"id" doc:"Unique user identifier" example:"123"`
Name string `json:"name" doc:"User's full name" example:"John Doe"`
Email string `json:"email" doc:"User's email address" example:"john@example.com"`
}
Generates:
type: object
properties:
id:
type: integer
description: Unique user identifier
example: 123
name:
type: string
description: User's full name
example: John Doe
email:
type: string
description: User's email address
example: john@example.com
Enum Types
Use enum tag to specify allowed values:
type User struct {
Role string `json:"role" enum:"admin,user,guest"`
Status string `json:"status" enum:"active,inactive,pending"`
}
Generates:
type: object
properties:
role:
type: string
enum: [admin, user, guest]
status:
type: string
enum: [active, inactive, pending]
Complete Schema Example
Here’s a comprehensive example using all features:
package main
import (
"time"
)
type User struct {
// Basic types
ID int `json:"id" doc:"Unique user identifier" example:"123"`
Name string `json:"name" doc:"User's full name" example:"John Doe" validate:"required"`
Email string `json:"email" doc:"Email address" example:"john@example.com" validate:"required,email"`
// Optional field
Bio *string `json:"bio,omitempty" doc:"User biography"`
// Numeric types
Age int `json:"age" doc:"User's age" validate:"min=0,max=150"`
Score float64 `json:"score" doc:"User score" example:"95.5"`
// Boolean
Active bool `json:"active" doc:"Whether user is active" example:"true"`
// Enum
Role string `json:"role" doc:"User role" enum:"admin,user,guest"`
// Arrays
Tags []string `json:"tags" doc:"User tags"`
Scores []int `json:"scores" doc:"Test scores"`
// Map
Metadata map[string]string `json:"metadata" doc:"Additional metadata"`
// Nested struct
Address Address `json:"address" doc:"User address"`
// Time
CreatedAt time.Time `json:"created_at" doc:"Creation timestamp"`
UpdatedAt *time.Time `json:"updated_at,omitempty" doc:"Last update timestamp"`
// Ignored field
Internal string `json:"-"`
}
type Address struct {
Street string `json:"street" validate:"required"`
City string `json:"city" validate:"required"`
State string `json:"state"`
ZipCode string `json:"zip_code" validate:"required"`
Country string `json:"country" validate:"required"`
}
Next Steps
- Learn about Operations to use your schemas in API endpoints
- Explore Validation to validate generated specifications
- See Examples for complete schema patterns
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.