Skip to content

Migrating from v2

There are some incompatible changes that were introduced in v3 of the codegen.

Extensions:

The following extensions are no longer supported:
- x-order
- x-oapi-codegen-only-honour-go-name

User templates

HTTP path is not supported

Custom name normalizer

Not supported

Server code generation

Server code generation is now supported with a completely redesigned architecture. v3 uses a unified generate.handler configuration with a clean service interface pattern that separates HTTP concerns from business logic.

Architecture comparison

Aspect v2 v3
Interface pattern ServerInterface with HTTP types in signature ServiceInterface with typed request/response structs
Handler signature FindPets(w http.ResponseWriter, r *http.Request, params FindPetsParams) FindPets(ctx context.Context, opts *FindPetsServiceRequestOptions) (*FindPetsResponseData, error)
Response handling Manual JSON encoding and status codes Return typed response, adapter handles encoding
Request parsing Parameters parsed, body manual All parsing done by adapter
Middleware Framework-specific, manual setup Scaffold generated with examples
Server main.go Not generated Optional generation with full middleware stack
Scaffold files Not generated service.go, middleware.go generated once

Code comparison

// v2: You implement ServerInterface with HTTP types
type ServerInterface interface {
    // (GET /pets)
    FindPets(w http.ResponseWriter, r *http.Request, params FindPetsParams)
}

// Your implementation mixes HTTP and business logic
func (s *Server) FindPets(w http.ResponseWriter, r *http.Request, params FindPetsParams) {
    pets, err := s.db.FindPets(params.Tags, params.Limit)
    if err != nil {
        w.WriteHeader(http.StatusInternalServerError)
        json.NewEncoder(w).Encode(map[string]string{"error": err.Error()})
        return
    }
    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(http.StatusOK)
    json.NewEncoder(w).Encode(pets)
}
// v3: You implement ServiceInterface with typed structs
type ServiceInterface interface {
    FindPets(ctx context.Context, opts *FindPetsServiceRequestOptions) (*FindPetsResponseData, error)
}

// Your implementation is pure business logic
func (s *Service) FindPets(ctx context.Context, opts *FindPetsServiceRequestOptions) (*FindPetsResponseData, error) {
    pets, err := s.db.FindPets(opts.Query.Tags, opts.Query.Limit)
    if err != nil {
        return nil, err  // Adapter returns 500
    }
    return NewFindPetsResponseData(&FindPetsResponse200{
        Pets: pets,
    }), nil
}

Configuration migration

package: api
output: gen.go
generate:
  chi-server: true
  models: true
package: api
output:
  directory: api
generate:
  handler:
    kind: chi
    middleware: {}
    server:
      directory: server
      handler-package: github.com/myorg/myapi/api

Framework support comparison

Framework v2 v3
chi chi-server chi
Echo echo-server echo
Gin gin-server gin
Fiber fiber-server fiber
gorilla/mux gorilla-server gorilla-mux
std-http std-http-server std-http
Iris iris-server iris
strict-server strict-server ❌ (service pattern is similar)
Beego beego
go-zero go-zero
Kratos kratos
GoFrame goframe
Hertz hertz
fasthttp fasthttp

About strict-server

v2's strict-server provided typed request/response objects similar to v3's service pattern. If you were using strict-server, the v3 service interface pattern should feel familiar, but with cleaner separation and scaffold generation.

See Server Generation for complete documentation.

Overlay support

v3 supports OpenAPI Overlays, allowing you to modify specs without editing the original files:

overlay:
  sources:
    - ./overlays/add-go-names.yaml
    - https://example.com/shared-overlay.yaml

See Overlays documentation for details.

Configuration changes

package: 
generate: 
    iris-server: ❌ not supported
    chi-server: ➡️ use generate.handler.kind: chi
    fiber-server: ➡️ use generate.handler.kind: fiber
    echo-server: ➡️ use generate.handler.kind: echo
    gin-server: ➡️ use generate.handler.kind: gin
    gorilla-server: ➡️ use generate.handler.kind: gorilla-mux
    std-http-server: ➡️ use generate.handler.kind: std-http
    strict-server: ❌ not supported
    client: 
      🆕🐣new properties:
        name: string
        timeout: time.duration
    models: ❌ always generated
    embedded-spec: 
    server-urls: 
  🆕🐣new properties:
    omit-description: bool
    default-int-type: "int64"
    handler:
      kind: string (chi, echo, gin, fiber, std-http, beego, go-zero, kratos, gorilla-mux, goframe, hertz, iris, fasthttp)
      name: string
      middleware: {}
      server:
        directory: string
        port: int
        timeout: int
        handler-package: string
compatibility: 
output-options: ➡️renamed to output
    skip-fmt: 
    skip-prune: ➡ moved to config root
    include-tags: ➡ moved to filter include
    exclude-tags: ➡ moved to filter.exclude
    include-operation-ids: ➡ moved to filter.include
    exclude-operation-ids: ➡ moved to filter.exclude
    user-templates: ➡ moved to the config root
    exclude-schemas: ❌ moved to filter.exclude
    response-type-suffix: 
    client-type-name: ➡ moved to generate.client.name
    initialism-overrides: 
    additional-initialisms: 
    nullable-type: 
    disable-type-aliases-for-type: 
    name-normalizer: 
    overlay: ➡️ moved to config root as overlay.sources
    yaml-tags: 
    client-response-bytes-function: 
    prefer-skip-optional-pointer: 
    prefer-skip-optional-pointer-with-omitzero: 
    prefer-skip-optional-pointer-on-container-types: 

  🆕🐣new properties:
    use-single-file: bool
    directory: string
    filename: string
import-mapping: 
additional-imports: