Repository: deepmap/oapi-codegen
Pull request #934 (2023-01-23 19:23:06)

Assign values of type Map in deep objects
This might be able to help with handling `additionalProperties` arbitrary maps as described in #930.


Patch:
diff --git a/README.md b/README.md
index c916753..f51aa46 100644
--- a/README.md
+++ b/README.md
@@ -40,7 +40,7 @@ into objects which match the OpenAPI 3.0 definition. The code generator in this
 directory does a lot of that for you. You would run it like so:
 
     go install github.com/deepmap/oapi-codegen/cmd/oapi-codegen@latest
-    oapi-codegen petstore-expanded.yaml > petstore.gen.go
+    oapi-codegen -package petstore petstore-expanded.yaml > petstore.gen.go
 
 Let's go through that `petstore.gen.go` file to show you everything which was
 generated.
diff --git a/cmd/oapi-codegen/oapi-codegen.go b/cmd/oapi-codegen/oapi-codegen.go
index aa33a76..ea9e008 100644
--- a/cmd/oapi-codegen/oapi-codegen.go
+++ b/cmd/oapi-codegen/oapi-codegen.go
@@ -42,17 +42,18 @@ var (
 	flagPrintVersion   bool
 	flagPackageName    string
 	flagPrintUsage     bool
+	flagGenerate       string
+	flagTemplatesDir   string
 
-	// The options below are deprecated, and they will be removed in a future
+	// Deprecated: The options below will be removed in a future
 	// release. Please use the new config file format.
-	flagGenerate           string
 	flagIncludeTags        string
 	flagExcludeTags        string
-	flagTemplatesDir       string
 	flagImportMapping      string
 	flagExcludeSchemas     string
 	flagResponseTypeSuffix string
 	flagAliasTypes         bool
+	flagInitalismOverrides bool
 )
 
 type configuration struct {
@@ -98,6 +99,7 @@ func main() {
 	flag.StringVar(&flagExcludeSchemas, "exclude-schemas", "", "A comma separated list of schemas which must be excluded from generation")
 	flag.StringVar(&flagResponseTypeSuffix, "response-type-suffix", "", "the suffix used for responses types")
 	flag.BoolVar(&flagAliasTypes, "alias-types", false, "Alias type declarations of possible")
+	flag.BoolVar(&flagInitalismOverrides, "initialism-overrides", false, "Use initialism overrides")
 
 	flag.Parse()
 
@@ -164,10 +166,8 @@ func main() {
 		// config style. It should work correctly if we go down the old path,
 		// even if we have a simple config file readable as both types.
 		deprecatedFlagNames := map[string]bool{
-			"generate":             true,
 			"include-tags":         true,
 			"exclude-tags":         true,
-			"templates":            true,
 			"import-mapping":       true,
 			"exclude-schemas":      true,
 			"response-type-suffix": true,
@@ -216,9 +216,8 @@ func main() {
 				OutputFile: flagOutputFile,
 			}
 		}
-		var err error
-		opts, err = updateConfigFromFlags(opts)
-		if err != nil {
+
+		if err := updateConfigFromFlags(&opts); err != nil {
 			errExit("error processing flags: %v\n", err)
 		}
 	} else {
@@ -352,51 +351,56 @@ func detectPackageName(cfg *configuration) error {
 }
 
 // updateConfigFromFlags updates a loaded configuration from flags. Flags
-// override anything in the file. We generate errors for command line options
-// associated with the old style configuration
-func updateConfigFromFlags(cfg configuration) (configuration, error) {
+// override anything in the file. We generate errors for any unsupported
+// command line flags.
+func updateConfigFromFlags(cfg *configuration) error {
 	if flagPackageName != "" {
 		cfg.PackageName = flagPackageName
 	}
 
-	var unsupportedFlags []string
-
 	if flagGenerate != "types,client,server,spec" {
-		unsupportedFlags = append(unsupportedFlags, "--generate")
+		// Override generation and output options from generate command line flag.
+		if err := generationTargets(&cfg.Configuration, util.ParseCommandLineList(flagGenerate)); err != nil {
+			return err
+		}
 	}
 	if flagIncludeTags != "" {
-		unsupportedFlags = append(unsupportedFlags, "--include-tags")
+		cfg.OutputOptions.IncludeTags = util.ParseCommandLineList(flagIncludeTags)
 	}
 	if flagExcludeTags != "" {
-		unsupportedFlags = append(unsupportedFlags, "--exclude-tags")
+		cfg.OutputOptions.ExcludeTags = util.ParseCommandLineList(flagExcludeTags)
 	}
 	if flagTemplatesDir != "" {
-		unsupportedFlags = append(unsupportedFlags, "--templates")
+		templates, err := loadTemplateOverrides(flagTemplatesDir)
+		if err != nil {
+			return fmt.Errorf("load templates from %q: %w", flagTemplatesDir, err)
+		}
+		cfg.OutputOptions.UserTemplates = templates
 	}
 	if flagImportMapping != "" {
-		unsupportedFlags = append(unsupportedFlags, "--import-mapping")
+		var err error
+		cfg.ImportMapping, err = util.ParseCommandlineMap(flagImportMapping)
+		if err != nil {
+			return err
+		}
 	}
 	if flagExcludeSchemas != "" {
-		unsupportedFlags = append(unsupportedFlags, "--exclude-schemas")
+		cfg.OutputOptions.ExcludeSchemas = util.ParseCommandLineList(flagExcludeSchemas)
 	}
 	if flagResponseTypeSuffix != "" {
-		unsupportedFlags = append(unsupportedFlags, "--response-type-suffix")
+		cfg.OutputOptions.ResponseTypeSuffix = flagResponseTypeSuffix
 	}
 	if flagAliasTypes {
-		unsupportedFlags = append(unsupportedFlags, "--alias-types")
-	}
-
-	if len(unsupportedFlags) > 0 {
-		return configuration{}, fmt.Errorf("flags %s aren't supported in "+
-			"new config style, please use --old-config-style or update your configuration ",
-			strings.Join(unsupportedFlags, ", "))
+		return fmt.Errorf("--alias-types isn't supported any more")
 	}
 
 	if cfg.OutputFile == "" {
 		cfg.OutputFile = flagOutputFile
 	}
 
-	return cfg, nil
+	cfg.OutputOptions.InitialismOverrides = flagInitalismOverrides
+
+	return nil
 }
 
 // updateOldConfigFromFlags parses the flags and the config file. Anything which is
@@ -434,6 +438,40 @@ func updateOldConfigFromFlags(cfg oldConfiguration) oldConfiguration {
 	return cfg
 }
 
+// generationTargets sets cfg options based on the generation targets.
+func generationTargets(cfg *codegen.Configuration, targets []string) error {
+	opts := codegen.GenerateOptions{} // Blank to start with.
+	for _, opt := range targets {
+		switch opt {
+		case "chi-server", "chi":
+			opts.ChiServer = true
+		case "server", "echo-server", "echo":
+			opts.EchoServer = true
+		case "gin", "gin-server":
+			opts.GinServer = true
+		case "gorilla", "gorilla-server":
+			opts.GorillaServer = true
+		case "strict-server":
+			opts.Strict = true
+		case "client":
+			opts.Client = true
+		case "types", "models":
+			opts.Models = true
+		case "spec", "embedded-spec":
+			opts.EmbeddedSpec = true
+		case "skip-fmt":
+			cfg.OutputOptions.SkipFmt = true
+		case "skip-prune":
+			cfg.OutputOptions.SkipPrune = true
+		default:
+			return fmt.Errorf("unknown generate option %q", opt)
+		}
+	}
+	cfg.Generate = opts
+
+	return nil
+}
+
 func newConfigFromOldConfig(c oldConfiguration) configuration {
 	// Take flags into account.
 	cfg := updateOldConfigFromFlags(c)
@@ -445,33 +483,10 @@ func newConfigFromOldConfig(c oldConfiguration) configuration {
 	}
 	opts.OutputOptions.ResponseTypeSuffix = flagResponseTypeSuffix
 
-	for _, g := range cfg.GenerateTargets {
-		switch g {
-		case "client":
-			opts.Generate.Client = true
-		case "chi-server":
-			opts.Generate.ChiServer = true
-		case "server":
-			opts.Generate.EchoServer = true
-		case "gin":
-			opts.Generate.GinServer = true
-		case "gorilla":
-			opts.Generate.GorillaServer = true
-		case "strict-server":
-			opts.Generate.Strict = true
-		case "types":
-			opts.Generate.Models = true
-		case "spec":
-			opts.Generate.EmbeddedSpec = true
-		case "skip-fmt":
-			opts.OutputOptions.SkipFmt = true
-		case "skip-prune":
-			opts.OutputOptions.SkipPrune = true
-		default:
-			fmt.Printf("unknown generate option %s\n", g)
-			flag.PrintDefaults()
-			os.Exit(1)
-		}
+	if err := generationTargets(&opts, cfg.GenerateTargets); err != nil {
+		fmt.Println(err)
+		flag.PrintDefaults()
+		os.Exit(1)
 	}
 
 	opts.OutputOptions.IncludeTags = cfg.IncludeTags
diff --git a/examples/authenticated-api/echo/api/api.gen.go b/examples/authenticated-api/echo/api/api.gen.go
index 1433f2d..1d0fcb1 100644
--- a/examples/authenticated-api/echo/api/api.gen.go
+++ b/examples/authenticated-api/echo/api/api.gen.go
@@ -425,7 +425,7 @@ type ServerInterfaceWrapper struct {
 func (w *ServerInterfaceWrapper) ListThings(ctx echo.Context) error {
 	var err error
 
-	ctx.Set(BearerAuthScopes, []string{""})
+	ctx.Set(BearerAuthScopes, []string{})
 
 	// Invoke the callback with all the unmarshalled arguments
 	err = w.Handler.ListThings(ctx)
diff --git a/examples/authenticated-api/echo/server/jwt_authenticator.go b/examples/authenticated-api/echo/server/jwt_authenticator.go
index 4d6b334..2c1699b 100644
--- a/examples/authenticated-api/echo/server/jwt_authenticator.go
+++ b/examples/authenticated-api/echo/server/jwt_authenticator.go
@@ -7,6 +7,7 @@ import (
 	"net/http"
 	"strings"
 
+	"github.com/deepmap/oapi-codegen/pkg/middleware"
 	"github.com/getkin/kin-openapi/openapi3filter"
 	"github.com/lestrrat-go/jwx/jwt"
 )
@@ -17,6 +18,8 @@ type JWSValidator interface {
 	ValidateJWS(jws string) (jwt.Token, error)
 }
 
+const JWTClaimsContextKey = "jwt_claims"
+
 var (
 	ErrNoAuthHeader      = errors.New("Authorization header is missing")
 	ErrInvalidAuthHeader = errors.New("Authorization header is malformed")
@@ -73,6 +76,12 @@ func Authenticate(v JWSValidator, ctx context.Context, input *openapi3filter.Aut
 	if err != nil {
 		return fmt.Errorf("token claims don't match: %w", err)
 	}
+
+	// Set the property on the echo context so the handler is able to
+	// access the claims data we generate in here.
+	eCtx := middleware.GetEchoContext(ctx)
+	eCtx.Set(JWTClaimsContextKey, token)
+
 	return nil
 }
 
diff --git a/examples/petstore-expanded/strict/api/petstore-server.gen.go b/examples/petstore-expanded/strict/api/petstore-server.gen.go
index cd9352a..822dee7 100644
--- a/examples/petstore-expanded/strict/api/petstore-server.gen.go
+++ b/examples/petstore-expanded/strict/api/petstore-server.gen.go
@@ -408,9 +408,8 @@ type StrictServerInterface interface {
 	FindPetByID(ctx context.Context, request FindPetByIDRequestObject) (FindPetByIDResponseObject, error)
 }
 
-type StrictHandlerFunc func(ctx context.Context, w http.ResponseWriter, r *http.Request, args interface{}) (interface{}, error)
-
-type StrictMiddlewareFunc func(f StrictHandlerFunc, operationID string) StrictHandlerFunc
+type StrictHandlerFunc = runtime.StrictHttpHandlerFunc
+type StrictMiddlewareFunc = runtime.StrictHttpMiddlewareFunc
 
 type StrictHTTPServerOptions struct {
 	RequestErrorHandlerFunc  func(w http.ResponseWriter, r *http.Request, err error)
diff --git a/go.mod b/go.mod
index cd07c4f..240683f 100644
--- a/go.mod
+++ b/go.mod
@@ -2,35 +2,38 @@ module github.com/deepmap/oapi-codegen
 
 require (
 	github.com/apapsch/go-jsonmerge/v2 v2.0.0
-	github.com/getkin/kin-openapi v0.112.0
-	github.com/gin-gonic/gin v1.8.2
+	github.com/getkin/kin-openapi v0.116.0
+	github.com/gin-gonic/gin v1.9.0
 	github.com/go-chi/chi/v5 v5.0.8
 	github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219
 	github.com/google/uuid v1.3.0
 	github.com/gorilla/mux v1.8.0
-	github.com/labstack/echo/v4 v4.10.0
+	github.com/labstack/echo/v4 v4.10.2
 	github.com/lestrrat-go/jwx v1.2.25
-	github.com/matryer/moq v0.3.0
-	github.com/stretchr/testify v1.8.1
-	golang.org/x/text v0.6.0
-	golang.org/x/tools v0.5.0
+	github.com/matryer/moq v0.3.1
+	github.com/stretchr/testify v1.8.2
+	golang.org/x/text v0.9.0
+	golang.org/x/tools v0.8.0
 	gopkg.in/yaml.v2 v2.4.0
 )
 
 require (
+	github.com/bytedance/sonic v1.8.0 // indirect
+	github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
 	github.com/davecgh/go-spew v1.1.1 // indirect
 	github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
 	github.com/gin-contrib/sse v0.1.0 // indirect
 	github.com/go-openapi/jsonpointer v0.19.5 // indirect
 	github.com/go-openapi/swag v0.21.1 // indirect
-	github.com/go-playground/locales v0.14.0 // indirect
-	github.com/go-playground/universal-translator v0.18.0 // indirect
-	github.com/go-playground/validator/v10 v10.11.1 // indirect
-	github.com/goccy/go-json v0.9.11 // indirect
+	github.com/go-playground/locales v0.14.1 // indirect
+	github.com/go-playground/universal-translator v0.18.1 // indirect
+	github.com/go-playground/validator/v10 v10.11.2 // indirect
+	github.com/goccy/go-json v0.10.0 // indirect
 	github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
 	github.com/invopop/yaml v0.1.0 // indirect
 	github.com/josharian/intern v1.0.0 // indirect
 	github.com/json-iterator/go v1.1.12 // indirect
+	github.com/klauspost/cpuid/v2 v2.0.9 // indirect
 	github.com/labstack/gommon v0.4.0 // indirect
 	github.com/leodido/go-urn v1.2.1 // indirect
 	github.com/lestrrat-go/backoff/v2 v2.0.8 // indirect
@@ -40,22 +43,25 @@ require (
 	github.com/lestrrat-go/option v1.0.0 // indirect
 	github.com/mailru/easyjson v0.7.7 // indirect
 	github.com/mattn/go-colorable v0.1.13 // indirect
-	github.com/mattn/go-isatty v0.0.16 // indirect
+	github.com/mattn/go-isatty v0.0.17 // indirect
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
 	github.com/modern-go/reflect2 v1.0.2 // indirect
 	github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
 	github.com/pelletier/go-toml/v2 v2.0.6 // indirect
+	github.com/perimeterx/marshmallow v1.1.4 // indirect
 	github.com/pkg/errors v0.9.1 // indirect
 	github.com/pmezard/go-difflib v1.0.0 // indirect
 	github.com/stretchr/objx v0.5.0 // indirect
-	github.com/ugorji/go/codec v1.2.7 // indirect
+	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
+	github.com/ugorji/go/codec v1.2.9 // indirect
 	github.com/valyala/bytebufferpool v1.0.0 // indirect
 	github.com/valyala/fasttemplate v1.2.2 // indirect
-	golang.org/x/crypto v0.2.0 // indirect
-	golang.org/x/mod v0.7.0 // indirect
-	golang.org/x/net v0.5.0 // indirect
-	golang.org/x/sys v0.4.0 // indirect
-	golang.org/x/time v0.2.0 // indirect
+	golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
+	golang.org/x/crypto v0.6.0 // indirect
+	golang.org/x/mod v0.10.0 // indirect
+	golang.org/x/net v0.9.0 // indirect
+	golang.org/x/sys v0.7.0 // indirect
+	golang.org/x/time v0.3.0 // indirect
 	golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f // indirect
 	google.golang.org/protobuf v1.28.1 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
diff --git a/go.sum b/go.sum
index 5fee8d8..f5edf9d 100644
--- a/go.sum
+++ b/go.sum
@@ -2,6 +2,12 @@ github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMz
 github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ=
 github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk=
 github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
+github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
+github.com/bytedance/sonic v1.8.0 h1:ea0Xadu+sHlu7x5O3gKhRpQ1IKiMrSiHttPF0ybECuA=
+github.com/bytedance/sonic v1.8.0/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
+github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
+github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
+github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
 github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@@ -10,12 +16,12 @@ github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn
 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d/go.mod h1:tmAIfUFEirG/Y8jhZ9M+h36obRZAk/1fcSpXwAVlfqE=
 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc=
 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs=
-github.com/getkin/kin-openapi v0.112.0 h1:lnLXx3bAG53EJVI4E/w0N8i1Y/vUZUEsnrXkgnfn7/Y=
-github.com/getkin/kin-openapi v0.112.0/go.mod h1:QtwUNt0PAAgIIBEvFWYfB7dfngxtAaqCX1zYHMZDeK8=
+github.com/getkin/kin-openapi v0.116.0 h1:o986hwgMzR972JzOG5j6+WTwWqllZLs1EJKMKCivs2E=
+github.com/getkin/kin-openapi v0.116.0/go.mod h1:l5e9PaFUo9fyLJCPGQeXI2ML8c3P8BHOEV2VaAVf/pc=
 github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
 github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
-github.com/gin-gonic/gin v1.8.2 h1:UzKToD9/PoFj/V4rvlKqTRKnQYyz8Sc1MJlv4JHPtvY=
-github.com/gin-gonic/gin v1.8.2/go.mod h1:qw5AYuDrzRTnhvusDsrov+fDIxp9Dleuu12h8nfB398=
+github.com/gin-gonic/gin v1.9.0 h1:OjyFBKICoexlu99ctXNR2gg+c5pKrKMuyjgARg9qeY8=
+github.com/gin-gonic/gin v1.9.0/go.mod h1:W1Me9+hsUSyj3CePGrd1/QrKJMSJ1Tu/0hFEH89961k=
 github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0=
 github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
 github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
@@ -23,17 +29,18 @@ github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34
 github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
 github.com/go-openapi/swag v0.21.1 h1:wm0rhTb5z7qpJRHBdPOMuY4QjVUMbF6/kwoYeRAOrKU=
 github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
-github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
-github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
-github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=
-github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
-github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
-github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
-github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ=
-github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
+github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
+github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
+github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
+github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
+github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
+github.com/go-playground/validator/v10 v10.11.2 h1:q3SHpufmypg+erIExEKUmsgmhDTyhcJ38oeKGACXohU=
+github.com/go-playground/validator/v10 v10.11.2/go.mod h1:NieE624vt4SCTJtD87arVLvdmjPAeV8BQlHtMnw9D7s=
+github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
+github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
 github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
-github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk=
-github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
+github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA=
+github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
 github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
 github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
 github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
@@ -53,16 +60,16 @@ github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFF
 github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
 github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
 github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE=
+github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
+github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
-github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
 github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
-github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
-github.com/labstack/echo/v4 v4.10.0 h1:5CiyngihEO4HXsz3vVsJn7f8xAlWwRr3aY6Ih280ZKA=
-github.com/labstack/echo/v4 v4.10.0/go.mod h1:S/T/5fy/GigaXnHTkh0ZGe4LpkkQysvRjFMSUTkDRNQ=
+github.com/labstack/echo/v4 v4.10.2 h1:n1jAhnq/elIFTHr1EYpiYtyKgx4RW9ccVgkqByZaN2M=
+github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k=
 github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
 github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
 github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
@@ -84,14 +91,15 @@ github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN
 github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
 github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
 github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
-github.com/matryer/moq v0.3.0 h1:4j0goF/XK3pMTc7fJB3fveuTJoQNdavRX/78vlK3Xb4=
-github.com/matryer/moq v0.3.0/go.mod h1:RJ75ZZZD71hejp39j4crZLsEDszGk6iH4v4YsWFKH4s=
+github.com/matryer/moq v0.3.1 h1:kLDiBJoGcusWS2BixGyTkF224aSCD8nLY24tj/NcTCs=
+github.com/matryer/moq v0.3.1/go.mod h1:RJ75ZZZD71hejp39j4crZLsEDszGk6iH4v4YsWFKH4s=
 github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
 github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
 github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
 github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
-github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
 github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
+github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
 github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -102,14 +110,13 @@ github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwd
 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
 github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
 github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
-github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
+github.com/perimeterx/marshmallow v1.1.4 h1:pZLDH9RjlLGGorbXhcaQLhfuV0pFMNfPO55FuFkxqLw=
+github.com/perimeterx/marshmallow v1.1.4/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
 github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
 github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
-github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
 github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
@@ -121,46 +128,49 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
-github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
 github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
+github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
+github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
 github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
-github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
 github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
+github.com/ugorji/go/codec v1.2.9 h1:rmenucSohSTiyL09Y+l2OCk+FrMxGMzho2+tjr5ticU=
+github.com/ugorji/go/codec v1.2.9/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
 github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
 github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
 github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
 github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
 github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
-golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
+golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
 golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.2.0 h1:BRXPfhNivWL5Yq0BGQ39a2sW6t44aODpfxkWjYdzewE=
-golang.org/x/crypto v0.2.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
-golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA=
-golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc=
+golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
+golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
+golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw=
-golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
+golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
+golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
 golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
-golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
+golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k=
-golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/time v0.2.0 h1:52I/1L54xyEQAYdtcSuxtiT84KGYTBGXwayxmIpNJhE=
-golang.org/x/time v0.2.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
+golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
+golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.5.0 h1:+bSpV5HIeWkuvgaMfI3UmKRThoTA5ODJTUd8T17NO+4=
-golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k=
+golang.org/x/tools v0.8.0 h1:vSDcovVPld282ceKgDimkRSC8kpaH1dgyc9UMzlt84Y=
+golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f h1:GGU+dLjvlC3qDwqYgL6UgRmHXhOOgns0bZu2Ty5mm6U=
 golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -171,8 +181,6 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
-gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
-gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
@@ -182,3 +190,4 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C
 gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
diff --git a/pkg/codegen/codegen.go b/pkg/codegen/codegen.go
index 062dc95..70dca56 100644
--- a/pkg/codegen/codegen.go
+++ b/pkg/codegen/codegen.go
@@ -138,7 +138,7 @@ func Generate(spec *openapi3.T, opts Configuration) (string, error) {
 		}
 	}
 
-	ops, err := OperationDefinitions(spec)
+	ops, err := OperationDefinitions(spec, opts.OutputOptions.InitialismOverrides)
 	if err != nil {
 		return "", fmt.Errorf("error creating operation definitions: %w", err)
 	}
@@ -201,9 +201,12 @@ func Generate(spec *openapi3.T, opts Configuration) (string, error) {
 
 	var strictServerOut string
 	if opts.Generate.Strict {
-		responses, err := GenerateResponseDefinitions("", spec.Components.Responses)
-		if err != nil {
-			return "", fmt.Errorf("error generation response definitions for schema: %w", err)
+		var responses []ResponseDefinition
+		if spec.Components != nil {
+			responses, err = GenerateResponseDefinitions("", spec.Components.Responses)
+			if err != nil {
+				return "", fmt.Errorf("error generation response definitions for schema: %w", err)
+			}
 		}
 		strictServerResponses, err := GenerateStrictResponses(t, responses)
 		if err != nil {
@@ -339,28 +342,31 @@ func Generate(spec *openapi3.T, opts Configuration) (string, error) {
 }
 
 func GenerateTypeDefinitions(t *template.Template, swagger *openapi3.T, ops []OperationDefinition, excludeSchemas []string) (string, error) {
-	schemaTypes, err := GenerateTypesForSchemas(t, swagger.Components.Schemas, excludeSchemas)
-	if err != nil {
-		return "", fmt.Errorf("error generating Go types for component schemas: %w", err)
-	}
+	var allTypes []TypeDefinition
+	if swagger.Components != nil {
+		schemaTypes, err := GenerateTypesForSchemas(t, swagger.Components.Schemas, excludeSchemas)
+		if err != nil {
+			return "", fmt.Errorf("error generating Go types for component schemas: %w", err)
+		}
 
-	paramTypes, err := GenerateTypesForParameters(t, swagger.Components.Parameters)
-	if err != nil {
-		return "", fmt.Errorf("error generating Go types for component parameters: %w", err)
-	}
-	allTypes := append(schemaTypes, paramTypes...)
+		paramTypes, err := GenerateTypesForParameters(t, swagger.Components.Parameters)
+		if err != nil {
+			return "", fmt.Errorf("error generating Go types for component parameters: %w", err)
+		}
+		allTypes = append(schemaTypes, paramTypes...)
 
-	responseTypes, err := GenerateTypesForResponses(t, swagger.Components.Responses)
-	if err != nil {
-		return "", fmt.Errorf("error generating Go types for component responses: %w", err)
-	}
-	allTypes = append(allTypes, responseTypes...)
+		responseTypes, err := GenerateTypesForResponses(t, swagger.Components.Responses)
+		if err != nil {
+			return "", fmt.Errorf("error generating Go types for component responses: %w", err)
+		}
+		allTypes = append(allTypes, responseTypes...)
 
-	bodyTypes, err := GenerateTypesForRequestBodies(t, swagger.Components.RequestBodies)
-	if err != nil {
-		return "", fmt.Errorf("error generating Go types for component request bodies: %w", err)
+		bodyTypes, err := GenerateTypesForRequestBodies(t, swagger.Components.RequestBodies)
+		if err != nil {
+			return "", fmt.Errorf("error generating Go types for component request bodies: %w", err)
+		}
+		allTypes = append(allTypes, bodyTypes...)
 	}
-	allTypes = append(allTypes, bodyTypes...)
 
 	// Go through all operations, and add their types to allTypes, so that we can
 	// scan all of them for enums. Operation definitions are handled differently
@@ -893,6 +899,10 @@ func OperationImports(ops []OperationDefinition) (map[string]goImport, error) {
 
 func GetTypeDefinitionsImports(swagger *openapi3.T, excludeSchemas []string) (map[string]goImport, error) {
 	res := map[string]goImport{}
+	if swagger.Components == nil {
+		return res, nil
+	}
+
 	schemaImports, err := GetSchemaImports(swagger.Components.Schemas, excludeSchemas)
 	if err != nil {
 		return nil, err
diff --git a/pkg/codegen/configuration.go b/pkg/codegen/configuration.go
index afa4fc5..8d7f2e6 100644
--- a/pkg/codegen/configuration.go
+++ b/pkg/codegen/configuration.go
@@ -84,9 +84,10 @@ type OutputOptions struct {
 	ExcludeTags   []string          `yaml:"exclude-tags,omitempty"`   // Exclude operations that have one of these tags. Ignored when empty.
 	UserTemplates map[string]string `yaml:"user-templates,omitempty"` // Override built-in templates from user-provided files
 
-	ExcludeSchemas     []string `yaml:"exclude-schemas,omitempty"`      // Exclude from generation schemas with given names. Ignored when empty.
-	ResponseTypeSuffix string   `yaml:"response-type-suffix,omitempty"` // The suffix used for responses types
-	ClientTypeName     string   `yaml:"client-type-name,omitempty"`     // Override the default generated client type with the value
+	ExcludeSchemas      []string `yaml:"exclude-schemas,omitempty"`      // Exclude from generation schemas with given names. Ignored when empty.
+	ResponseTypeSuffix  string   `yaml:"response-type-suffix,omitempty"` // The suffix used for responses types
+	ClientTypeName      string   `yaml:"client-type-name,omitempty"`     // Override the default generated client type with the value
+	InitialismOverrides bool     `yaml:"initialism-overrides,omitempty"` // Whether to use the initialism overrides
 }
 
 // UpdateDefaults sets reasonable default values for unset fields in Configuration
diff --git a/pkg/codegen/extension.go b/pkg/codegen/extension.go
index ad91ad0..ca4c3b6 100644
--- a/pkg/codegen/extension.go
+++ b/pkg/codegen/extension.go
@@ -1,7 +1,6 @@
 package codegen
 
 import (
-	"encoding/json"
 	"fmt"
 )
 
@@ -13,24 +12,20 @@ const (
 	// extGoName is used to override a field name
 	extGoName = "x-go-name"
 	// extGoTypeName is used to override a generated typename for something.
-	extGoTypeName       = "x-go-type-name"
-	extPropGoJsonIgnore = "x-go-json-ignore"
-	extPropOmitEmpty    = "x-omitempty"
-	extPropExtraTags    = "x-oapi-codegen-extra-tags"
-	extEnumVarNames     = "x-enum-varnames"
-	extEnumNames        = "x-enumNames"
+	extGoTypeName        = "x-go-type-name"
+	extPropGoJsonIgnore  = "x-go-json-ignore"
+	extPropOmitEmpty     = "x-omitempty"
+	extPropExtraTags     = "x-oapi-codegen-extra-tags"
+	extEnumVarNames      = "x-enum-varnames"
+	extEnumNames         = "x-enumNames"
+	extDeprecationReason = "x-deprecated-reason"
 )
 
 func extString(extPropValue interface{}) (string, error) {
-	raw, ok := extPropValue.(json.RawMessage)
+	str, ok := extPropValue.(string)
 	if !ok {
 		return "", fmt.Errorf("failed to convert type: %T", extPropValue)
 	}
-	var str string
-	if err := json.Unmarshal(raw, &str); err != nil {
-		return "", fmt.Errorf("failed to unmarshal json: %w", err)
-	}
-
 	return str, nil
 }
 func extTypeName(extPropValue interface{}) (string, error) {
@@ -42,53 +37,53 @@ func extParseGoFieldName(extPropValue interface{}) (string, error) {
 }
 
 func extParseOmitEmpty(extPropValue interface{}) (bool, error) {
-	raw, ok := extPropValue.(json.RawMessage)
+	omitEmpty, ok := extPropValue.(bool)
 	if !ok {
 		return false, fmt.Errorf("failed to convert type: %T", extPropValue)
 	}
-
-	var omitEmpty bool
-	if err := json.Unmarshal(raw, &omitEmpty); err != nil {
-		return false, fmt.Errorf("failed to unmarshal json: %w", err)
-	}
-
 	return omitEmpty, nil
 }
 
 func extExtraTags(extPropValue interface{}) (map[string]string, error) {
-	raw, ok := extPropValue.(json.RawMessage)
+	tagsI, ok := extPropValue.(map[string]interface{})
 	if !ok {
 		return nil, fmt.Errorf("failed to convert type: %T", extPropValue)
 	}
-	var tags map[string]string
-	if err := json.Unmarshal(raw, &tags); err != nil {
-		return nil, fmt.Errorf("failed to unmarshal json: %w", err)
+	tags := make(map[string]string, len(tagsI))
+	for k, v := range tagsI {
+		vs, ok := v.(string)
+		if !ok {
+			return nil, fmt.Errorf("failed to convert type: %T", v)
+		}
+		tags[k] = vs
 	}
 	return tags, nil
 }
 
 func extParseGoJsonIgnore(extPropValue interface{}) (bool, error) {
-	raw, ok := extPropValue.(json.RawMessage)
+	goJsonIgnore, ok := extPropValue.(bool)
 	if !ok {
 		return false, fmt.Errorf("failed to convert type: %T", extPropValue)
 	}
-
-	var goJsonIgnore bool
-	if err := json.Unmarshal(raw, &goJsonIgnore); err != nil {
-		return false, fmt.Errorf("failed to unmarshal json: %w", err)
-	}
-
 	return goJsonIgnore, nil
 }
 
 func extParseEnumVarNames(extPropValue interface{}) ([]string, error) {
-	raw, ok := extPropValue.(json.RawMessage)
+	namesI, ok := extPropValue.([]interface{})
 	if !ok {
 		return nil, fmt.Errorf("failed to convert type: %T", extPropValue)
 	}
-	var names []string
-	if err := json.Unmarshal(raw, &names); err != nil {
-		return nil, fmt.Errorf("failed to unmarshal json: %w", err)
+	names := make([]string, len(namesI))
+	for i, v := range namesI {
+		vs, ok := v.(string)
+		if !ok {
+			return nil, fmt.Errorf("failed to convert type: %T", v)
+		}
+		names[i] = vs
 	}
 	return names, nil
 }
+
+func extParseDeprecationReason(extPropValue interface{}) (string, error) {
+	return extString(extPropValue)
+}
diff --git a/pkg/codegen/merge_schemas.go b/pkg/codegen/merge_schemas.go
index 466e55c..84256b1 100644
--- a/pkg/codegen/merge_schemas.go
+++ b/pkg/codegen/merge_schemas.go
@@ -53,10 +53,10 @@ func valueWithPropagatedRef(ref *openapi3.SchemaRef) (openapi3.Schema, error) {
 	}
 
 	pathParts := strings.Split(ref.Ref, "#")
-	if len(pathParts) != 2 {
+	if len(pathParts) < 1 || len(pathParts) > 2 {
 		return openapi3.Schema{}, fmt.Errorf("unsupported reference: %s", ref.Ref)
 	}
-	remoteComponent, _ := pathParts[0], pathParts[1]
+	remoteComponent := pathParts[0]
 
 	// remote ref
 	schema := *ref.Value
@@ -212,11 +212,11 @@ func mergeOpenapiSchemas(s1, s2 openapi3.Schema, allOf bool) (openapi3.Schema, e
 	if SchemaHasAdditionalProperties(&s1) && SchemaHasAdditionalProperties(&s2) {
 		return openapi3.Schema{}, errors.New("merging two schemas with additional properties, this is unhandled")
 	}
-	if s1.AdditionalProperties != nil {
-		result.AdditionalProperties = s1.AdditionalProperties
+	if s1.AdditionalProperties.Schema != nil {
+		result.AdditionalProperties.Schema = s1.AdditionalProperties.Schema
 	}
-	if s2.AdditionalProperties != nil {
-		result.AdditionalProperties = s2.AdditionalProperties
+	if s2.AdditionalProperties.Schema != nil {
+		result.AdditionalProperties.Schema = s2.AdditionalProperties.Schema
 	}
 
 	// Allow discriminators for allOf merges, but disallow for one/anyOfs.
diff --git a/pkg/codegen/operations.go b/pkg/codegen/operations.go
index 314e894..01666ff 100644
--- a/pkg/codegen/operations.go
+++ b/pkg/codegen/operations.go
@@ -126,8 +126,8 @@ func (pd ParameterDefinition) GoVariableName() string {
 
 func (pd ParameterDefinition) GoName() string {
 	goName := pd.ParamName
-	if _, ok := pd.Spec.ExtensionProps.Extensions[extGoName]; ok {
-		if extGoFieldName, err := extParseGoFieldName(pd.Spec.ExtensionProps.Extensions[extGoName]); err == nil {
+	if _, ok := pd.Spec.Extensions[extGoName]; ok {
+		if extGoFieldName, err := extParseGoFieldName(pd.Spec.Extensions[extGoName]); err == nil {
 			goName = extGoFieldName
 		}
 	}
@@ -293,7 +293,11 @@ func (o *OperationDefinition) GetResponseTypeDefinitions() ([]ResponseTypeDefini
 
 					var typeName string
 					switch {
-					case StringInArray(contentTypeName, contentTypesJSON):
+					// HAL+JSON:
+					case StringInArray(contentTypeName, contentTypesHalJSON):
+						typeName = fmt.Sprintf("HALJSON%s", ToCamelCase(responseName))
+					// JSON:
+					case StringInArray(contentTypeName, contentTypesJSON) || util.IsMediaTypeJson(contentTypeName):
 						typeName = fmt.Sprintf("JSON%s", ToCamelCase(responseName))
 					// YAML:
 					case StringInArray(contentTypeName, contentTypesYAML):
@@ -483,9 +487,16 @@ func FilterParameterDefinitionByType(params []ParameterDefinition, in string) []
 }
 
 // OperationDefinitions returns all operations for a swagger definition.
-func OperationDefinitions(swagger *openapi3.T) ([]OperationDefinition, error) {
+func OperationDefinitions(swagger *openapi3.T, initialismOverrides bool) ([]OperationDefinition, error) {
 	var operations []OperationDefinition
 
+	var toCamelCaseFunc func(string) string
+	if initialismOverrides {
+		toCamelCaseFunc = ToCamelCaseWithInitialism
+	} else {
+		toCamelCaseFunc = ToCamelCase
+	}
+
 	for _, requestPath := range SortedPathsKeys(swagger.Paths) {
 		pathItem := swagger.Paths[requestPath]
 		// These are parameters defined for all methods on a given path. They
@@ -505,13 +516,13 @@ func OperationDefinitions(swagger *openapi3.T) ([]OperationDefinition, error) {
 			}
 			// We rely on OperationID to generate function names, it's required
 			if op.OperationID == "" {
-				op.OperationID, err = generateDefaultOperationID(opName, requestPath)
+				op.OperationID, err = generateDefaultOperationID(opName, requestPath, toCamelCaseFunc)
 				if err != nil {
 					return nil, fmt.Errorf("error generating default OperationID for %s/%s: %s",
 						opName, requestPath, err)
 				}
 			} else {
-				op.OperationID = ToCamelCase(op.OperationID)
+				op.OperationID = toCamelCaseFunc(op.OperationID)
 			}
 			op.OperationID = typeNamePrefix(op.OperationID) + op.OperationID
 
@@ -550,7 +561,7 @@ func OperationDefinitions(swagger *openapi3.T) ([]OperationDefinition, error) {
 				HeaderParams: FilterParameterDefinitionByType(allParams, "header"),
 				QueryParams:  FilterParameterDefinitionByType(allParams, "query"),
 				CookieParams: FilterParameterDefinitionByType(allParams, "cookie"),
-				OperationId:  ToCamelCase(op.OperationID),
+				OperationId:  toCamelCaseFunc(op.OperationID),
 				// Replace newlines in summary.
 				Summary:         op.Summary,
 				Method:          opName,
@@ -588,7 +599,7 @@ func OperationDefinitions(swagger *openapi3.T) ([]OperationDefinition, error) {
 	return operations, nil
 }
 
-func generateDefaultOperationID(opName string, requestPath string) (string, error) {
+func generateDefaultOperationID(opName string, requestPath string, toCamelCaseFunc func(string) string) (string, error) {
 	var operationId = strings.ToLower(opName)
 
 	if opName == "" {
@@ -605,7 +616,7 @@ func generateDefaultOperationID(opName string, requestPath string) (string, erro
 		}
 	}
 
-	return ToCamelCase(operationId), nil
+	return toCamelCaseFunc(operationId), nil
 }
 
 // GenerateBodyDefinitions turns the Swagger body definitions into a list of our body
@@ -663,6 +674,17 @@ func GenerateBodyDefinitions(operationID string, bodyOrRef *openapi3.RequestBody
 		// type under #/components, we'll define a type for it, so
 		// that we have an easy to use type for marshaling.
 		if bodySchema.RefType == "" {
+			if contentType == "application/x-www-form-urlencoded" {
+				// Apply the appropriate structure tag if the request
+				// schema was defined under the operations' section.
+				for i := range bodySchema.Properties {
+					bodySchema.Properties[i].NeedsFormTag = true
+				}
+
+				// Regenerate the Golang struct adding the new form tag.
+				bodySchema.GoType = GenStructFromSchema(bodySchema)
+			}
+
 			td := TypeDefinition{
 				TypeName: bodyTypeName,
 				Schema:   bodySchema,
@@ -825,12 +847,12 @@ func GenerateParamsTypes(op OperationDefinition) []TypeDefinition {
 			})
 		}
 		prop := Property{
-			Description:    param.Spec.Description,
-			JsonFieldName:  param.ParamName,
-			Required:       param.Required,
-			Schema:         pSchema,
-			NeedsFormTag:   param.Style() == "form",
-			ExtensionProps: &param.Spec.ExtensionProps,
+			Description:   param.Spec.Description,
+			JsonFieldName: param.ParamName,
+			Required:      param.Required,
+			Schema:        pSchema,
+			NeedsFormTag:  param.Style() == "form",
+			Extensions:    param.Spec.Extensions,
 		}
 		s.Properties = append(s.Properties, prop)
 	}
diff --git a/pkg/codegen/prune.go b/pkg/codegen/prune.go
index 03df80f..9dc4fd8 100644
--- a/pkg/codegen/prune.go
+++ b/pkg/codegen/prune.go
@@ -35,7 +35,7 @@ func walkSwagger(swagger *openapi3.T, doFn func(RefWrapper) (bool, error)) error
 		}
 	}
 
-	_ = walkComponents(&swagger.Components, doFn)
+	_ = walkComponents(swagger.Components, doFn)
 
 	return nil
 }
@@ -144,7 +144,7 @@ func walkSchemaRef(ref *openapi3.SchemaRef, doFn func(RefWrapper) (bool, error))
 		_ = walkSchemaRef(ref, doFn)
 	}
 
-	_ = walkSchemaRef(ref.Value.AdditionalProperties, doFn)
+	_ = walkSchemaRef(ref.Value.AdditionalProperties.Schema, doFn)
 
 	return nil
 }
@@ -392,6 +392,10 @@ func findComponentRefs(swagger *openapi3.T) []string {
 }
 
 func removeOrphanedComponents(swagger *openapi3.T, refs []string) int {
+	if swagger.Components == nil {
+		return 0
+	}
+
 	countRemoved := 0
 
 	for key := range swagger.Components.Schemas {
diff --git a/pkg/codegen/schema.go b/pkg/codegen/schema.go
index 1843024..92f72b4 100644
--- a/pkg/codegen/schema.go
+++ b/pkg/codegen/schema.go
@@ -1,6 +1,7 @@
 package codegen
 
 import (
+	"errors"
 	"fmt"
 	"strings"
 
@@ -70,20 +71,26 @@ func (s Schema) GetAdditionalTypeDefs() []TypeDefinition {
 	for _, p := range s.Properties {
 		result = append(result, p.Schema.GetAdditionalTypeDefs()...)
 	}
+	// Some schema definitions may be used for key/value and not specify any properties, but provide properties
+	// within the additionalProperties. See test_schema_array_types.yaml in tests.
+	if s.AdditionalPropertiesType != nil {
+		result = append(result, s.AdditionalPropertiesType.GetAdditionalTypeDefs()...)
+	}
 	result = append(result, s.AdditionalTypes...)
 	return result
 }
 
 type Property struct {
-	Description    string
-	JsonFieldName  string
-	Schema         Schema
-	Required       bool
-	Nullable       bool
-	ReadOnly       bool
-	WriteOnly      bool
-	NeedsFormTag   bool
-	ExtensionProps *openapi3.ExtensionProps
+	Description   string
+	JsonFieldName string
+	Schema        Schema
+	Required      bool
+	Nullable      bool
+	ReadOnly      bool
+	WriteOnly     bool
+	NeedsFormTag  bool
+	Extensions    map[string]interface{}
+	Deprecated    bool
 }
 
 func (p Property) GoFieldName() string {
@@ -308,8 +315,8 @@ func GenerateGoSchema(sref *openapi3.SchemaRef, path []string) (Schema, error) {
 
 			// If additional properties are defined, we will override the default
 			// above with the specific definition.
-			if schema.AdditionalProperties != nil {
-				additionalSchema, err := GenerateGoSchema(schema.AdditionalProperties, path)
+			if schema.AdditionalProperties.Schema != nil {
+				additionalSchema, err := GenerateGoSchema(schema.AdditionalProperties.Schema, path)
 				if err != nil {
 					return Schema{}, fmt.Errorf("error generating type for additional properties: %w", err)
 				}
@@ -379,14 +386,15 @@ func GenerateGoSchema(sref *openapi3.SchemaRef, path []string) (Schema, error) {
 					description = p.Value.Description
 				}
 				prop := Property{
-					JsonFieldName:  pName,
-					Schema:         pSchema,
-					Required:       required,
-					Description:    description,
-					Nullable:       p.Value.Nullable,
-					ReadOnly:       p.Value.ReadOnly,
-					WriteOnly:      p.Value.WriteOnly,
-					ExtensionProps: &p.Value.ExtensionProps,
+					JsonFieldName: pName,
+					Schema:        pSchema,
+					Required:      required,
+					Description:   description,
+					Nullable:      p.Value.Nullable,
+					ReadOnly:      p.Value.ReadOnly,
+					WriteOnly:     p.Value.WriteOnly,
+					Extensions:    p.Value.Extensions,
+					Deprecated:    p.Value.Deprecated,
 				}
 				outSchema.Properties = append(outSchema.Properties, prop)
 			}
@@ -422,8 +430,8 @@ func GenerateGoSchema(sref *openapi3.SchemaRef, path []string) (Schema, error) {
 
 		enumNames := enumValues
 		for _, key := range []string{extEnumVarNames, extEnumNames} {
-			if _, ok := schema.ExtensionProps.Extensions[key]; ok {
-				if extEnumNames, err := extParseEnumVarNames(schema.ExtensionProps.Extensions[key]); err == nil {
+			if _, ok := schema.Extensions[key]; ok {
+				if extEnumNames, err := extParseEnumVarNames(schema.Extensions[key]); err == nil {
 					enumNames = extEnumNames
 					break
 				}
@@ -605,8 +613,8 @@ func GenFieldsFromProperties(props []Property) []string {
 		field := ""
 
 		goFieldName := p.GoFieldName()
-		if _, ok := p.ExtensionProps.Extensions[extGoName]; ok {
-			if extGoFieldName, err := extParseGoFieldName(p.ExtensionProps.Extensions[extGoName]); err == nil {
+		if _, ok := p.Extensions[extGoName]; ok {
+			if extGoFieldName, err := extParseGoFieldName(p.Extensions[extGoName]); err == nil {
 				goFieldName = extGoFieldName
 			}
 		}
@@ -621,19 +629,34 @@ func GenFieldsFromProperties(props []Property) []string {
 			field += fmt.Sprintf("%s\n", StringWithTypeNameToGoComment(p.Description, p.GoFieldName()))
 		}
 
+		if p.Deprecated {
+			// This comment has to be on its own line for godoc & IDEs to pick up
+			var deprecationReason string
+			if _, ok := p.Extensions[extDeprecationReason]; ok {
+				if extOmitEmpty, err := extParseDeprecationReason(p.Extensions[extDeprecationReason]); err == nil {
+					deprecationReason = extOmitEmpty
+				}
+			}
+
+			field += fmt.Sprintf("%s\n", DeprecationComment(deprecationReason))
+		}
+
 		field += fmt.Sprintf("    %s %s", goFieldName, p.GoTypeDef())
 
+		omitEmpty := !p.Nullable &&
+			(!p.Required || p.ReadOnly || p.WriteOnly) &&
+			(!p.Required || !p.ReadOnly || !globalState.options.Compatibility.DisableRequiredReadOnlyAsPointer)
+
 		// Support x-omitempty
-		overrideOmitEmpty := true
-		if _, ok := p.ExtensionProps.Extensions[extPropOmitEmpty]; ok {
-			if extOmitEmpty, err := extParseOmitEmpty(p.ExtensionProps.Extensions[extPropOmitEmpty]); err == nil {
-				overrideOmitEmpty = extOmitEmpty
+		if extOmitEmptyValue, ok := p.Extensions[extPropOmitEmpty]; ok {
+			if extOmitEmpty, err := extParseOmitEmpty(extOmitEmptyValue); err == nil {
+				omitEmpty = extOmitEmpty
 			}
 		}
 
 		fieldTags := make(map[string]string)
 
-		if (p.Required && !p.ReadOnly && !p.WriteOnly) || p.Nullable || !overrideOmitEmpty || (p.Required && p.ReadOnly && globalState.options.Compatibility.DisableRequiredReadOnlyAsPointer) {
+		if !omitEmpty {
 			fieldTags["json"] = p.JsonFieldName
 			if p.NeedsFormTag {
 				fieldTags["form"] = p.JsonFieldName
@@ -646,14 +669,14 @@ func GenFieldsFromProperties(props []Property) []string {
 		}
 
 		// Support x-go-json-ignore
-		if _, ok := p.ExtensionProps.Extensions[extPropGoJsonIgnore]; ok {
-			if goJsonIgnore, err := extParseGoJsonIgnore(p.ExtensionProps.Extensions[extPropGoJsonIgnore]); err == nil && goJsonIgnore {
+		if _, ok := p.Extensions[extPropGoJsonIgnore]; ok {
+			if goJsonIgnore, err := extParseGoJsonIgnore(p.Extensions[extPropGoJsonIgnore]); err == nil && goJsonIgnore {
 				fieldTags["json"] = "-"
 			}
 		}
 
 		// Support x-oapi-codegen-extra-tags
-		if extension, ok := p.ExtensionProps.Extensions[extPropExtraTags]; ok {
+		if extension, ok := p.Extensions[extPropExtraTags]; ok {
 			if tags, err := extExtraTags(extension); err == nil {
 				keys := SortedStringKeys(tags)
 				for _, k := range keys {
@@ -759,15 +782,30 @@ func generateUnion(outSchema *Schema, elements openapi3.SchemaRefs, discriminato
 		}
 
 		if discriminator != nil {
+			if len(discriminator.Mapping) != 0 && element.Ref == "" {
+				return errors.New("ambiguous discriminator.mapping: please replace inlined object with $ref")
+			}
+
+			// Explicit mapping.
+			var mapped bool
 			for k, v := range discriminator.Mapping {
 				if v == element.Ref {
 					outSchema.Discriminator.Mapping[k] = elementSchema.GoType
+					mapped = true
 					break
 				}
 			}
+			// Implicit mapping.
+			if !mapped {
+				outSchema.Discriminator.Mapping[RefPathToObjName(element.Ref)] = elementSchema.GoType
+			}
 		}
 		outSchema.UnionElements = append(outSchema.UnionElements, UnionElement(elementSchema.GoType))
 	}
 
+	if (outSchema.Discriminator != nil) && len(outSchema.Discriminator.Mapping) != len(elements) {
+		return errors.New("discriminator: not all schemas were mapped")
+	}
+
 	return nil
 }
diff --git a/pkg/codegen/template_helpers.go b/pkg/codegen/template_helpers.go
index 7585a26..bae1e30 100644
--- a/pkg/codegen/template_helpers.go
+++ b/pkg/codegen/template_helpers.go
@@ -34,9 +34,10 @@ const (
 )
 
 var (
-	contentTypesJSON = []string{echo.MIMEApplicationJSON, "text/x-json", "application/problem+json"}
-	contentTypesYAML = []string{"application/yaml", "application/x-yaml", "text/yaml", "text/x-yaml"}
-	contentTypesXML  = []string{echo.MIMEApplicationXML, echo.MIMETextXML, "application/problems+xml"}
+	contentTypesJSON    = []string{echo.MIMEApplicationJSON, "text/x-json", "application/problem+json"}
+	contentTypesHalJSON = []string{"application/hal+json"}
+	contentTypesYAML    = []string{"application/yaml", "application/x-yaml", "text/yaml", "text/x-yaml"}
+	contentTypesXML     = []string{echo.MIMEApplicationXML, echo.MIMETextXML, "application/problems+xml"}
 
 	responseTypeSuffix = "Response"
 
@@ -263,7 +264,11 @@ func getConditionOfResponseName(statusCodeVar, responseName string) string {
 
 // This outputs a string array
 func toStringArray(sarr []string) string {
-	return `[]string{"` + strings.Join(sarr, `","`) + `"}`
+	s := strings.Join(sarr, `","`)
+	if len(s) > 0 {
+		s = `"` + s + `"`
+	}
+	return `[]string{` + s + `}`
 }
 
 func stripNewLines(s string) string {
diff --git a/pkg/codegen/templates/strict/strict-echo.tmpl b/pkg/codegen/templates/strict/strict-echo.tmpl
index c858c09..86def37 100644
--- a/pkg/codegen/templates/strict/strict-echo.tmpl
+++ b/pkg/codegen/templates/strict/strict-echo.tmpl
@@ -1,6 +1,5 @@
-type StrictHandlerFunc func(ctx echo.Context, args interface{}) (interface{}, error)
-
-type StrictMiddlewareFunc func(f StrictHandlerFunc, operationID string) StrictHandlerFunc
+type StrictHandlerFunc = runtime.StrictEchoHandlerFunc
+type StrictMiddlewareFunc = runtime.StrictEchoMiddlewareFunc
 
 func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc) ServerInterface {
     return &strictHandler{ssi: ssi, middlewares: middlewares}
@@ -18,8 +17,7 @@ type strictHandler struct {
         var request {{$opid | ucFirst}}RequestObject
 
         {{range .PathParams -}}
-            {{$varName := .GoVariableName -}}
-            request.{{$varName | ucFirst}} = {{$varName}}
+            request.{{.GoName}} = {{.GoVariableName}}
         {{end -}}
 
         {{if .RequiresParamObject -}}
diff --git a/pkg/codegen/templates/strict/strict-gin.tmpl b/pkg/codegen/templates/strict/strict-gin.tmpl
index 8097e28..0c36f40 100644
--- a/pkg/codegen/templates/strict/strict-gin.tmpl
+++ b/pkg/codegen/templates/strict/strict-gin.tmpl
@@ -1,6 +1,5 @@
-type StrictHandlerFunc func(ctx *gin.Context, args interface{}) (interface{}, error)
-
-type StrictMiddlewareFunc func(f StrictHandlerFunc, operationID string) StrictHandlerFunc
+type StrictHandlerFunc = runtime.StrictGinHandlerFunc
+type StrictMiddlewareFunc = runtime.StrictGinMiddlewareFunc
 
 func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc) ServerInterface {
     return &strictHandler{ssi: ssi, middlewares: middlewares}
@@ -18,8 +17,7 @@ type strictHandler struct {
         var request {{$opid | ucFirst}}RequestObject
 
         {{range .PathParams -}}
-            {{$varName := .GoVariableName -}}
-            request.{{$varName | ucFirst}} = {{$varName}}
+            request.{{.GoName}} = {{.GoVariableName}}
         {{end -}}
 
         {{if .RequiresParamObject -}}
@@ -84,6 +82,7 @@ type strictHandler struct {
 
         if err != nil {
             ctx.Error(err)
+            ctx.Status(http.StatusInternalServerError)
         } else if validResponse, ok := response.({{$opid | ucFirst}}ResponseObject); ok {
             if err := validResponse.Visit{{$opid}}Response(ctx.Writer); err != nil {
                 ctx.Error(err)
diff --git a/pkg/codegen/templates/strict/strict-http.tmpl b/pkg/codegen/templates/strict/strict-http.tmpl
index b1d2e9d..b16ed1d 100644
--- a/pkg/codegen/templates/strict/strict-http.tmpl
+++ b/pkg/codegen/templates/strict/strict-http.tmpl
@@ -1,6 +1,5 @@
-type StrictHandlerFunc func(ctx context.Context, w http.ResponseWriter, r *http.Request, args interface{}) (interface{}, error)
-
-type StrictMiddlewareFunc func(f StrictHandlerFunc, operationID string) StrictHandlerFunc
+type StrictHandlerFunc = runtime.StrictHttpHandlerFunc
+type StrictMiddlewareFunc = runtime.StrictHttpMiddlewareFunc
 
 type StrictHTTPServerOptions struct {
     RequestErrorHandlerFunc  func(w http.ResponseWriter, r *http.Request, err error)
@@ -35,8 +34,7 @@ type strictHandler struct {
         var request {{$opid | ucFirst}}RequestObject
 
         {{range .PathParams -}}
-            {{$varName := .GoVariableName -}}
-            request.{{$varName | ucFirst}} = {{$varName}}
+            request.{{.GoName}} = {{.GoVariableName}}
         {{end -}}
 
         {{if .RequiresParamObject -}}
diff --git a/pkg/codegen/templates/union.tmpl b/pkg/codegen/templates/union.tmpl
index 06c91f4..8bb34a2 100644
--- a/pkg/codegen/templates/union.tmpl
+++ b/pkg/codegen/templates/union.tmpl
@@ -53,7 +53,7 @@
               return err
             }
 
-            merged, err := runtime.JsonMerge(b, t.union)
+            merged, err := runtime.JsonMerge(t.union, b)
             t.union = merged
             return err
         }
diff --git a/pkg/codegen/utils.go b/pkg/codegen/utils.go
index 7526ee3..3922538 100644
--- a/pkg/codegen/utils.go
+++ b/pkg/codegen/utils.go
@@ -14,10 +14,10 @@
 package codegen
 
 import (
-	"encoding/json"
 	"fmt"
 	"go/token"
 	"net/url"
+	"reflect"
 	"regexp"
 	"sort"
 	"strconv"
@@ -161,6 +161,24 @@ func ToCamelCase(str string) string {
 	return n
 }
 
+func ToCamelCaseWithInitialism(str string) string {
+	return replaceInitialism(ToCamelCase(str))
+}
+
+func replaceInitialism(s string) string {
+	// These strings do not apply CamelCase
+	// Do not do CamelCase when these characters match when the preceding character is lowercase
+	// ["Acl", "Api", "Ascii", "Cpu", "Css", "Dns", "Eof", "Guid", "Html", "Http", "Https", "Id", "Ip", "Json", "Qps", "Ram", "Rpc", "Sla", "Smtp", "Sql", "Ssh", "Tcp", "Tls", "Ttl", "Udp", "Ui", "Gid", "Uid", "Uuid", "Uri", "Url", "Utf8", "Vm", "Xml", "Xmpp", "Xsrf", "Xss", "Sip", "Rtp", "Amqp", "Db", "Ts"]
+	targetWordRegex := regexp.MustCompile(`(?i)(Acl|Api|Ascii|Cpu|Css|Dns|Eof|Guid|Html|Http|Https|Id|Ip|Json|Qps|Ram|Rpc|Sla|Smtp|Sql|Ssh|Tcp|Tls|Ttl|Udp|Ui|Gid|Uid|Uuid|Uri|Url|Utf8|Vm|Xml|Xmpp|Xsrf|Xss|Sip|Rtp|Amqp|Db|Ts)`)
+	return targetWordRegex.ReplaceAllStringFunc(s, func(s string) string {
+		// If the preceding character is lowercase, do not do CamelCase
+		if unicode.IsLower(rune(s[0])) {
+			return s
+		}
+		return strings.ToUpper(s)
+	})
+}
+
 // SortedSchemaKeys returns the keys of the given SchemaRef dictionary in sorted
 // order, since Golang scrambles dictionary keys
 func SortedSchemaKeys(dict map[string]*openapi3.SchemaRef) []string {
@@ -291,6 +309,23 @@ func StringInArray(str string, array []string) bool {
 	return false
 }
 
+// RefPathToObjName returns the name of referenced object without changes.
+//
+//	#/components/schemas/Foo -> Foo
+//	#/components/parameters/Bar -> Bar
+//	#/components/responses/baz_baz -> baz_baz
+//	document.json#/Foo -> Foo
+//	http://deepmap.com/schemas/document.json#/objObj -> objObj
+//
+// Does not check refPath correctness.
+func RefPathToObjName(refPath string) string {
+	parts := strings.Split(refPath, "/")
+	if len(parts) > 0 {
+		return parts[len(parts)-1]
+	}
+	return ""
+}
+
 // RefPathToGoType takes a $ref value and converts it to a Go typename.
 // #/components/schemas/Foo -> Foo
 // #/components/parameters/Bar -> Bar
@@ -646,11 +681,11 @@ func SchemaNameToTypeName(name string) string {
 // you must specify an additionalProperties type
 // If additionalProperties it true/false, this field will be non-nil.
 func SchemaHasAdditionalProperties(schema *openapi3.Schema) bool {
-	if schema.AdditionalPropertiesAllowed != nil && *schema.AdditionalPropertiesAllowed {
+	if schema.AdditionalProperties.Has != nil && *schema.AdditionalProperties.Has {
 		return true
 	}
 
-	if schema.AdditionalProperties != nil {
+	if schema.AdditionalProperties.Schema != nil {
 		return true
 	}
 	return false
@@ -678,6 +713,15 @@ func StringWithTypeNameToGoComment(in, typeName string) string {
 	return stringToGoCommentWithPrefix(in, typeName)
 }
 
+func DeprecationComment(reason string) string {
+	var content = "Deprecated:" // The colon is required at the end even without reason
+	if reason != "" {
+		content += fmt.Sprintf(" %s", reason)
+	}
+
+	return stringToGoCommentWithPrefix(content, "")
+}
+
 func stringToGoCommentWithPrefix(in, prefix string) string {
 	if len(in) == 0 || len(strings.TrimSpace(in)) == 0 { // ignore empty comment
 		return ""
@@ -840,15 +884,30 @@ func ParseGoImportExtension(v *openapi3.SchemaRef) (*goImport, error) {
 
 	goTypeImportExt := v.Value.Extensions[extPropGoImport]
 
-	if raw, ok := goTypeImportExt.(json.RawMessage); ok {
-		gi := goImport{}
-		if err := json.Unmarshal(raw, &gi); err != nil {
-			return nil, err
+	importI, ok := goTypeImportExt.(map[string]interface{})
+	if !ok {
+		return nil, fmt.Errorf("failed to convert type: %T", goTypeImportExt)
+	}
+
+	gi := goImport{}
+	// replicate the case-insensitive field mapping json.Unmarshal would do
+	for k, v := range importI {
+		if strings.EqualFold(k, "name") {
+			if vs, ok := v.(string); ok {
+				gi.Name = vs
+			} else {
+				return nil, fmt.Errorf("failed to convert type: %T", v)
+			}
+		} else if strings.EqualFold(k, "path") {
+			if vs, ok := v.(string); ok {
+				gi.Path = vs
+			} else {
+				return nil, fmt.Errorf("failed to convert type: %T", v)
+			}
 		}
-		return &gi, nil
 	}
 
-	return nil, nil
+	return &gi, nil
 }
 
 func MergeImports(dst, src map[string]goImport) {
@@ -864,5 +923,5 @@ func TypeDefinitionsEquivalent(t1, t2 TypeDefinition) bool {
 	if t1.TypeName != t2.TypeName {
 		return false
 	}
-	return t1.Schema.OAPISchema == t2.Schema.OAPISchema
+	return reflect.DeepEqual(t1.Schema.OAPISchema, t2.Schema.OAPISchema)
 }
diff --git a/pkg/runtime/deepobject.go b/pkg/runtime/deepobject.go
index 87e9dd9..35286b3 100644
--- a/pkg/runtime/deepobject.go
+++ b/pkg/runtime/deepobject.go
@@ -200,6 +200,19 @@ func assignPathValues(dst interface{}, pathValues fieldOrValue) error {
 	it := iv.Type()
 
 	switch it.Kind() {
+	case reflect.Map:
+		dstMap := reflect.MakeMap(iv.Type())
+		for key, value := range pathValues.fields {
+			dstKey := reflect.ValueOf(key)
+			dstVal := reflect.New(iv.Type().Elem())
+			err := assignPathValues(dstVal.Interface(), value)
+			if err != nil {
+				return fmt.Errorf("error binding map: %w", err)
+			}
+			dstMap.SetMapIndex(dstKey, dstVal.Elem())
+		}
+		iv.Set(dstMap)
+		return nil
 	case reflect.Slice:
 		sliceLength := len(pathValues.fields)
 		dstSlice := reflect.MakeSlice(it, sliceLength, sliceLength)
diff --git a/pkg/runtime/strictmiddleware.go b/pkg/runtime/strictmiddleware.go
new file mode 100644
index 0000000..fac240e
--- /dev/null
+++ b/pkg/runtime/strictmiddleware.go
@@ -0,0 +1,21 @@
+package runtime
+
+import (
+	"context"
+	"net/http"
+
+	"github.com/gin-gonic/gin"
+	"github.com/labstack/echo/v4"
+)
+
+type StrictEchoHandlerFunc func(ctx echo.Context, request interface{}) (response interface{}, err error)
+
+type StrictEchoMiddlewareFunc func(f StrictEchoHandlerFunc, operationID string) StrictEchoHandlerFunc
+
+type StrictHttpHandlerFunc func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (response interface{}, err error)
+
+type StrictHttpMiddlewareFunc func(f StrictHttpHandlerFunc, operationID string) StrictHttpHandlerFunc
+
+type StrictGinHandlerFunc func(ctx *gin.Context, request interface{}) (response interface{}, err error)
+
+type StrictGinMiddlewareFunc func(f StrictGinHandlerFunc, operationID string) StrictGinHandlerFunc
diff --git a/pkg/runtime/styleparam.go b/pkg/runtime/styleparam.go
index 8f7e129..06b2e25 100644
--- a/pkg/runtime/styleparam.go
+++ b/pkg/runtime/styleparam.go
@@ -27,6 +27,7 @@ import (
 	"time"
 
 	"github.com/deepmap/oapi-codegen/pkg/types"
+	"github.com/google/uuid"
 )
 
 // Parameter escaping works differently based on where a header is found
@@ -428,6 +429,10 @@ func primitiveToString(value interface{}) (string, error) {
 	case reflect.Struct:
 		// If input has Marshaler, such as object has Additional Property or AnyOf,
 		// We use this Marshaler and convert into interface{} before styling.
+		if v, ok := value.(uuid.UUID); ok {
+			output = v.String()
+			break
+		}
 		if m, ok := value.(json.Marshaler); ok {
 			buf, err := m.MarshalJSON()
 			if err != nil {


Test patch:
diff --git a/internal/test/any_of/param/param.gen.go b/internal/test/any_of/param/param.gen.go
index 7de9459..07dd59b 100644
--- a/internal/test/any_of/param/param.gen.go
+++ b/internal/test/any_of/param/param.gen.go
@@ -70,7 +70,7 @@ func (t *Test) MergeTest0(v Test0) error {
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -96,7 +96,7 @@ func (t *Test) MergeTest1(v Test1) error {
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -132,7 +132,7 @@ func (t *Test2) MergeTest20(v Test20) error {
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -158,7 +158,7 @@ func (t *Test2) MergeTest21(v Test21) error {
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
diff --git a/internal/test/components/components.gen.go b/internal/test/components/components.gen.go
index 4ed8b65..be29e17 100644
--- a/internal/test/components/components.gen.go
+++ b/internal/test/components/components.gen.go
@@ -170,7 +170,7 @@ type ObjectWithJsonField struct {
 	Value2 json.RawMessage `json:"value2,omitempty"`
 }
 
-// OneOfObject1 oneOf with references and no disciminator
+// OneOfObject1 oneOf with references and no discriminator
 type OneOfObject1 struct {
 	union json.RawMessage
 }
@@ -256,7 +256,7 @@ type OneOfObject4 struct {
 	union         json.RawMessage
 }
 
-// OneOfObject5 oneOf with disciminator but no mapping
+// OneOfObject5 oneOf with discriminator but no mapping
 type OneOfObject5 struct {
 	union json.RawMessage
 }
@@ -266,6 +266,16 @@ type OneOfObject6 struct {
 	union json.RawMessage
 }
 
+// OneOfObject61 oneOf with discriminator and partial mapping
+type OneOfObject61 struct {
+	union json.RawMessage
+}
+
+// OneOfObject62 oneOf with snake_case discriminator and partial snake_case mapping
+type OneOfObject62 struct {
+	union json.RawMessage
+}
+
 // OneOfObject7 array of oneOf
 type OneOfObject7 = []OneOfObject7_Item
 
@@ -337,6 +347,12 @@ type SchemaObject struct {
 	WriteOnlyRequiredProp *int    `json:"writeOnlyRequiredProp,omitempty"`
 }
 
+// OneOfVariant51 defines model for one_of_variant51.
+type OneOfVariant51 struct {
+	Discriminator string `json:"discriminator"`
+	Id            int    `json:"id"`
+}
+
 // EnumParam1 defines model for EnumParam1.
 type EnumParam1 string
 
@@ -817,7 +833,7 @@ func (t *AnyOfObject1) MergeOneOfVariant4(v OneOfVariant4) error {
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -843,7 +859,7 @@ func (t *AnyOfObject1) MergeOneOfVariant5(v OneOfVariant5) error {
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -879,7 +895,7 @@ func (t *OneOfObject1) MergeOneOfVariant1(v OneOfVariant1) error {
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -905,7 +921,7 @@ func (t *OneOfObject1) MergeOneOfVariant2(v OneOfVariant2) error {
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -931,7 +947,7 @@ func (t *OneOfObject1) MergeOneOfVariant3(v OneOfVariant3) error {
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -967,7 +983,7 @@ func (t *OneOfObject10) MergeOneOfObject100(v OneOfObject100) error {
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -993,7 +1009,7 @@ func (t *OneOfObject10) MergeOneOfObject101(v OneOfObject101) error {
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -1091,7 +1107,7 @@ func (t *OneOfObject11_AdditionalProperties) MergeOneOfObject110(v OneOfObject11
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -1117,7 +1133,7 @@ func (t *OneOfObject11_AdditionalProperties) MergeOneOfObject111(v OneOfObject11
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -1143,7 +1159,7 @@ func (t *OneOfObject11_AdditionalProperties) MergeOneOfObject112(v OneOfObject11
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -1179,7 +1195,7 @@ func (t *OneOfObject12) MergeOneOfObject120(v OneOfObject120) error {
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -1205,7 +1221,7 @@ func (t *OneOfObject12) MergeOneOfObject121(v OneOfObject121) error {
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -1231,7 +1247,7 @@ func (t *OneOfObject12) MergeOneOfVariant3(v OneOfVariant3) error {
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -1257,7 +1273,7 @@ func (t *OneOfObject12) MergeOneOfVariant4(v OneOfVariant4) error {
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -1297,7 +1313,7 @@ func (t *OneOfObject13) MergeOneOfVariant1(v OneOfVariant1) error {
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -1327,7 +1343,7 @@ func (t *OneOfObject13) MergeOneOfVariant6(v OneOfVariant6) error {
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -1376,7 +1392,7 @@ func (t *OneOfObject2) MergeOneOfObject20(v OneOfObject20) error {
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -1402,7 +1418,7 @@ func (t *OneOfObject2) MergeOneOfObject21(v OneOfObject21) error {
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -1428,7 +1444,7 @@ func (t *OneOfObject2) MergeOneOfObject22(v OneOfObject22) error {
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -1464,7 +1480,7 @@ func (t *OneOfObject3_Union) MergeOneOfVariant1(v OneOfVariant1) error {
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -1490,7 +1506,7 @@ func (t *OneOfObject3_Union) MergeOneOfVariant2(v OneOfVariant2) error {
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -1516,7 +1532,7 @@ func (t *OneOfObject3_Union) MergeOneOfVariant3(v OneOfVariant3) error {
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -1552,7 +1568,7 @@ func (t *OneOfObject4) MergeOneOfVariant1(v OneOfVariant1) error {
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -1578,7 +1594,7 @@ func (t *OneOfObject4) MergeOneOfVariant2(v OneOfVariant2) error {
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -1604,7 +1620,7 @@ func (t *OneOfObject4) MergeOneOfVariant3(v OneOfVariant3) error {
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -1662,6 +1678,7 @@ func (t OneOfObject5) AsOneOfVariant4() (OneOfVariant4, error) {
 
 // FromOneOfVariant4 overwrites any union data inside the OneOfObject5 as the provided OneOfVariant4
 func (t *OneOfObject5) FromOneOfVariant4(v OneOfVariant4) error {
+	v.Discriminator = "OneOfVariant4"
 	b, err := json.Marshal(v)
 	t.union = b
 	return err
@@ -1669,12 +1686,13 @@ func (t *OneOfObject5) FromOneOfVariant4(v OneOfVariant4) error {
 
 // MergeOneOfVariant4 performs a merge with any union data inside the OneOfObject5, using the provided OneOfVariant4
 func (t *OneOfObject5) MergeOneOfVariant4(v OneOfVariant4) error {
+	v.Discriminator = "OneOfVariant4"
 	b, err := json.Marshal(v)
 	if err != nil {
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -1688,6 +1706,7 @@ func (t OneOfObject5) AsOneOfVariant5() (OneOfVariant5, error) {
 
 // FromOneOfVariant5 overwrites any union data inside the OneOfObject5 as the provided OneOfVariant5
 func (t *OneOfObject5) FromOneOfVariant5(v OneOfVariant5) error {
+	v.Discriminator = "OneOfVariant5"
 	b, err := json.Marshal(v)
 	t.union = b
 	return err
@@ -1695,12 +1714,13 @@ func (t *OneOfObject5) FromOneOfVariant5(v OneOfVariant5) error {
 
 // MergeOneOfVariant5 performs a merge with any union data inside the OneOfObject5, using the provided OneOfVariant5
 func (t *OneOfObject5) MergeOneOfVariant5(v OneOfVariant5) error {
+	v.Discriminator = "OneOfVariant5"
 	b, err := json.Marshal(v)
 	if err != nil {
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -1713,6 +1733,21 @@ func (t OneOfObject5) Discriminator() (string, error) {
 	return discriminator.Discriminator, err
 }
 
+func (t OneOfObject5) ValueByDiscriminator() (interface{}, error) {
+	discriminator, err := t.Discriminator()
+	if err != nil {
+		return nil, err
+	}
+	switch discriminator {
+	case "OneOfVariant4":
+		return t.AsOneOfVariant4()
+	case "OneOfVariant5":
+		return t.AsOneOfVariant5()
+	default:
+		return nil, errors.New("unknown discriminator value: " + discriminator)
+	}
+}
+
 func (t OneOfObject5) MarshalJSON() ([]byte, error) {
 	b, err := t.union.MarshalJSON()
 	return b, err
@@ -1746,7 +1781,7 @@ func (t *OneOfObject6) MergeOneOfVariant4(v OneOfVariant4) error {
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -1774,7 +1809,7 @@ func (t *OneOfObject6) MergeOneOfVariant5(v OneOfVariant5) error {
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -1812,6 +1847,184 @@ func (t *OneOfObject6) UnmarshalJSON(b []byte) error {
 	return err
 }
 
+// AsOneOfVariant4 returns the union data inside the OneOfObject61 as a OneOfVariant4
+func (t OneOfObject61) AsOneOfVariant4() (OneOfVariant4, error) {
+	var body OneOfVariant4
+	err := json.Unmarshal(t.union, &body)
+	return body, err
+}
+
+// FromOneOfVariant4 overwrites any union data inside the OneOfObject61 as the provided OneOfVariant4
+func (t *OneOfObject61) FromOneOfVariant4(v OneOfVariant4) error {
+	v.Discriminator = "v4"
+	b, err := json.Marshal(v)
+	t.union = b
+	return err
+}
+
+// MergeOneOfVariant4 performs a merge with any union data inside the OneOfObject61, using the provided OneOfVariant4
+func (t *OneOfObject61) MergeOneOfVariant4(v OneOfVariant4) error {
+	v.Discriminator = "v4"
+	b, err := json.Marshal(v)
+	if err != nil {
+		return err
+	}
+
+	merged, err := runtime.JsonMerge(t.union, b)
+	t.union = merged
+	return err
+}
+
+// AsOneOfVariant5 returns the union data inside the OneOfObject61 as a OneOfVariant5
+func (t OneOfObject61) AsOneOfVariant5() (OneOfVariant5, error) {
+	var body OneOfVariant5
+	err := json.Unmarshal(t.union, &body)
+	return body, err
+}
+
+// FromOneOfVariant5 overwrites any union data inside the OneOfObject61 as the provided OneOfVariant5
+func (t *OneOfObject61) FromOneOfVariant5(v OneOfVariant5) error {
+	v.Discriminator = "OneOfVariant5"
+	b, err := json.Marshal(v)
+	t.union = b
+	return err
+}
+
+// MergeOneOfVariant5 performs a merge with any union data inside the OneOfObject61, using the provided OneOfVariant5
+func (t *OneOfObject61) MergeOneOfVariant5(v OneOfVariant5) error {
+	v.Discriminator = "OneOfVariant5"
+	b, err := json.Marshal(v)
+	if err != nil {
+		return err
+	}
+
+	merged, err := runtime.JsonMerge(t.union, b)
+	t.union = merged
+	return err
+}
+
+func (t OneOfObject61) Discriminator() (string, error) {
+	var discriminator struct {
+		Discriminator string `json:"discriminator"`
+	}
+	err := json.Unmarshal(t.union, &discriminator)
+	return discriminator.Discriminator, err
+}
+
+func (t OneOfObject61) ValueByDiscriminator() (interface{}, error) {
+	discriminator, err := t.Discriminator()
+	if err != nil {
+		return nil, err
+	}
+	switch discriminator {
+	case "OneOfVariant5":
+		return t.AsOneOfVariant5()
+	case "v4":
+		return t.AsOneOfVariant4()
+	default:
+		return nil, errors.New("unknown discriminator value: " + discriminator)
+	}
+}
+
+func (t OneOfObject61) MarshalJSON() ([]byte, error) {
+	b, err := t.union.MarshalJSON()
+	return b, err
+}
+
+func (t *OneOfObject61) UnmarshalJSON(b []byte) error {
+	err := t.union.UnmarshalJSON(b)
+	return err
+}
+
+// AsOneOfVariant4 returns the union data inside the OneOfObject62 as a OneOfVariant4
+func (t OneOfObject62) AsOneOfVariant4() (OneOfVariant4, error) {
+	var body OneOfVariant4
+	err := json.Unmarshal(t.union, &body)
+	return body, err
+}
+
+// FromOneOfVariant4 overwrites any union data inside the OneOfObject62 as the provided OneOfVariant4
+func (t *OneOfObject62) FromOneOfVariant4(v OneOfVariant4) error {
+	v.Discriminator = "variant_four"
+	b, err := json.Marshal(v)
+	t.union = b
+	return err
+}
+
+// MergeOneOfVariant4 performs a merge with any union data inside the OneOfObject62, using the provided OneOfVariant4
+func (t *OneOfObject62) MergeOneOfVariant4(v OneOfVariant4) error {
+	v.Discriminator = "variant_four"
+	b, err := json.Marshal(v)
+	if err != nil {
+		return err
+	}
+
+	merged, err := runtime.JsonMerge(t.union, b)
+	t.union = merged
+	return err
+}
+
+// AsOneOfVariant51 returns the union data inside the OneOfObject62 as a OneOfVariant51
+func (t OneOfObject62) AsOneOfVariant51() (OneOfVariant51, error) {
+	var body OneOfVariant51
+	err := json.Unmarshal(t.union, &body)
+	return body, err
+}
+
+// FromOneOfVariant51 overwrites any union data inside the OneOfObject62 as the provided OneOfVariant51
+func (t *OneOfObject62) FromOneOfVariant51(v OneOfVariant51) error {
+	v.Discriminator = "one_of_variant51"
+	b, err := json.Marshal(v)
+	t.union = b
+	return err
+}
+
+// MergeOneOfVariant51 performs a merge with any union data inside the OneOfObject62, using the provided OneOfVariant51
+func (t *OneOfObject62) MergeOneOfVariant51(v OneOfVariant51) error {
+	v.Discriminator = "one_of_variant51"
+	b, err := json.Marshal(v)
+	if err != nil {
+		return err
+	}
+
+	merged, err := runtime.JsonMerge(t.union, b)
+	t.union = merged
+	return err
+}
+
+func (t OneOfObject62) Discriminator() (string, error) {
+	var discriminator struct {
+		Discriminator string `json:"discriminator"`
+	}
+	err := json.Unmarshal(t.union, &discriminator)
+	return discriminator.Discriminator, err
+}
+
+func (t OneOfObject62) ValueByDiscriminator() (interface{}, error) {
+	discriminator, err := t.Discriminator()
+	if err != nil {
+		return nil, err
+	}
+	switch discriminator {
+	case "one_of_variant51":
+		return t.AsOneOfVariant51()
+	case "variant_four":
+		return t.AsOneOfVariant4()
+	default:
+		return nil, errors.New("unknown discriminator value: " + discriminator)
+	}
+}
+
+func (t OneOfObject62) MarshalJSON() ([]byte, error) {
+	b, err := t.union.MarshalJSON()
+	return b, err
+}
+
+func (t *OneOfObject62) UnmarshalJSON(b []byte) error {
+	err := t.union.UnmarshalJSON(b)
+	return err
+}
+
 // AsOneOfVariant1 returns the union data inside the OneOfObject7_Item as a OneOfVariant1
 func (t OneOfObject7_Item) AsOneOfVariant1() (OneOfVariant1, error) {
 	var body OneOfVariant1
@@ -1833,7 +2046,7 @@ func (t *OneOfObject7_Item) MergeOneOfVariant1(v OneOfVariant1) error {
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -1859,7 +2072,7 @@ func (t *OneOfObject7_Item) MergeOneOfVariant2(v OneOfVariant2) error {
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -1895,7 +2108,7 @@ func (t *OneOfObject8) MergeOneOfVariant1(v OneOfVariant1) error {
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -1921,7 +2134,7 @@ func (t *OneOfObject8) MergeOneOfVariant2(v OneOfVariant2) error {
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -1995,7 +2208,7 @@ func (t *OneOfObject9) MergeOneOfVariant1(v OneOfVariant1) error {
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
@@ -2025,7 +2238,7 @@ func (t *OneOfObject9) MergeOneOfVariant6(v OneOfVariant6) error {
 		return err
 	}
 
-	merged, err := runtime.JsonMerge(b, t.union)
+	merged, err := runtime.JsonMerge(t.union, b)
 	t.union = merged
 	return err
 }
diff --git a/internal/test/components/components.yaml b/internal/test/components/components.yaml
index 98224ed..24fdf77 100644
--- a/internal/test/components/components.yaml
+++ b/internal/test/components/components.yaml
@@ -208,7 +208,7 @@ components:
         additionalProperties:
           $ref: '#/components/schemas/SchemaObject'
     OneOfObject1:
-      description: oneOf with references and no disciminator
+      description: oneOf with references and no discriminator
       oneOf:
         - $ref: '#/components/schemas/OneOfVariant1'
         - $ref: '#/components/schemas/OneOfVariant2'
@@ -244,7 +244,7 @@ components:
         - $ref: '#/components/schemas/OneOfVariant2'
         - $ref: '#/components/schemas/OneOfVariant3'
     OneOfObject5:
-      description: oneOf with disciminator but no mapping
+      description: oneOf with discriminator but no mapping
       oneOf:
         - $ref: '#/components/schemas/OneOfVariant4'
         - $ref: '#/components/schemas/OneOfVariant5'
@@ -260,6 +260,24 @@ components:
         mapping:
           v4: '#/components/schemas/OneOfVariant4'
           v5: '#/components/schemas/OneOfVariant5'
+    OneOfObject61:
+      description: oneOf with discriminator and partial mapping
+      oneOf:
+        - $ref: '#/components/schemas/OneOfVariant4'
+        - $ref: '#/components/schemas/OneOfVariant5'
+      discriminator:
+        propertyName: discriminator
+        mapping:
+          v4: '#/components/schemas/OneOfVariant4'
+    OneOfObject62:
+      description: oneOf with snake_case discriminator and partial snake_case mapping
+      oneOf:
+        - $ref: '#/components/schemas/OneOfVariant4'
+        - $ref: '#/components/schemas/one_of_variant51'
+      discriminator:
+        propertyName: discriminator
+        mapping:
+          variant_four: '#/components/schemas/OneOfVariant4'
     OneOfObject7:
       description: array of oneOf
       type: array
@@ -380,6 +398,16 @@ components:
       required:
         - discriminator
         - id
+    one_of_variant51:
+      type: object
+      properties:
+        discriminator:
+          type: string
+        id:
+          type: integer
+      required:
+        - discriminator
+        - id
     OneOfVariant6:
       type: object
       properties:
diff --git a/internal/test/components/components_test.go b/internal/test/components/components_test.go
index e25ede2..7810ea2 100644
--- a/internal/test/components/components_test.go
+++ b/internal/test/components/components_test.go
@@ -9,15 +9,8 @@ import (
 )
 
 func assertJsonEqual(t *testing.T, j1 []byte, j2 []byte) {
-	var v1, v2 interface{}
-
-	err := json.Unmarshal(j1, &v1)
-	assert.NoError(t, err)
-
-	err = json.Unmarshal(j2, &v2)
-	assert.NoError(t, err)
-
-	assert.EqualValues(t, v1, v2)
+	t.Helper()
+	assert.JSONEq(t, string(j1), string(j2))
 }
 
 func TestRawJSON(t *testing.T) {
@@ -152,6 +145,117 @@ func TestOneOfWithDiscriminator(t *testing.T) {
 	assertJsonEqual(t, []byte(variant5), marshaled)
 }
 
+func TestOneOfWithDiscriminator_PartialMapping(t *testing.T) {
+	const variant4 = `{"discriminator": "v4", "name": "123"}`
+	const variant5 = `{"discriminator": "OneOfVariant5", "id": 321}`
+	var dst OneOfObject61
+
+	err := json.Unmarshal([]byte(variant4), &dst)
+	assert.NoError(t, err)
+	discriminator, err := dst.Discriminator()
+	require.NoError(t, err)
+	assert.Equal(t, "v4", discriminator)
+	v4, err := dst.ValueByDiscriminator()
+	require.NoError(t, err)
+	assert.Equal(t, OneOfVariant4{Discriminator: "v4", Name: "123"}, v4)
+
+	err = json.Unmarshal([]byte(variant5), &dst)
+	require.NoError(t, err)
+	discriminator, err = dst.Discriminator()
+	require.NoError(t, err)
+	assert.Equal(t, "OneOfVariant5", discriminator)
+	v5, err := dst.ValueByDiscriminator()
+	require.NoError(t, err)
+	assert.Equal(t, OneOfVariant5{Discriminator: "OneOfVariant5", Id: 321}, v5)
+
+	// discriminator value will be filled by the generated code
+	err = dst.FromOneOfVariant4(OneOfVariant4{Name: "123"})
+	require.NoError(t, err)
+	marshaled, err := json.Marshal(dst)
+	require.NoError(t, err)
+	assertJsonEqual(t, []byte(variant4), marshaled)
+
+	err = dst.FromOneOfVariant5(OneOfVariant5{Id: 321})
+	require.NoError(t, err)
+	marshaled, err = json.Marshal(dst)
+	require.NoError(t, err)
+	assertJsonEqual(t, []byte(variant5), marshaled)
+}
+
+func TestOneOfWithDiscriminator_SchemaNameUsed(t *testing.T) {
+	const variant4 = `{"discriminator": "variant_four", "name": "789"}`
+	const variant51 = `{"discriminator": "one_of_variant51", "id": 987}`
+	var dst OneOfObject62
+
+	err := json.Unmarshal([]byte(variant4), &dst)
+	assert.NoError(t, err)
+	discriminator, err := dst.Discriminator()
+	require.NoError(t, err)
+	assert.Equal(t, "variant_four", discriminator)
+	v4, err := dst.ValueByDiscriminator()
+	require.NoError(t, err)
+	assert.Equal(t, OneOfVariant4{Discriminator: "variant_four", Name: "789"}, v4)
+
+	err = json.Unmarshal([]byte(variant51), &dst)
+	require.NoError(t, err)
+	discriminator, err = dst.Discriminator()
+	require.NoError(t, err)
+	assert.Equal(t, "one_of_variant51", discriminator)
+	v5, err := dst.ValueByDiscriminator()
+	require.NoError(t, err)
+	assert.Equal(t, OneOfVariant51{Discriminator: "one_of_variant51", Id: 987}, v5)
+
+	// discriminator value will be filled by the generated code
+	err = dst.FromOneOfVariant4(OneOfVariant4{Name: "789"})
+	require.NoError(t, err)
+	marshaled, err := json.Marshal(dst)
+	require.NoError(t, err)
+	assertJsonEqual(t, []byte(variant4), marshaled)
+
+	err = dst.FromOneOfVariant51(OneOfVariant51{Id: 987})
+	require.NoError(t, err)
+	marshaled, err = json.Marshal(dst)
+	require.NoError(t, err)
+	assertJsonEqual(t, []byte(variant51), marshaled)
+}
+
+func TestOneOfWithDiscriminator_FullImplicitMapping(t *testing.T) {
+	const variant4 = `{"discriminator": "OneOfVariant4", "name": "456"}`
+	const variant5 = `{"discriminator": "OneOfVariant5", "id": 654}`
+	var dst OneOfObject5
+
+	err := json.Unmarshal([]byte(variant4), &dst)
+	assert.NoError(t, err)
+	discriminator, err := dst.Discriminator()
+	require.NoError(t, err)
+	assert.Equal(t, "OneOfVariant4", discriminator)
+	v4, err := dst.ValueByDiscriminator()
+	require.NoError(t, err)
+	assert.Equal(t, OneOfVariant4{Discriminator: "OneOfVariant4", Name: "456"}, v4)
+
+	err = json.Unmarshal([]byte(variant5), &dst)
+	require.NoError(t, err)
+	discriminator, err = dst.Discriminator()
+	require.NoError(t, err)
+	assert.Equal(t, "OneOfVariant5", discriminator)
+	v5, err := dst.ValueByDiscriminator()
+	require.NoError(t, err)
+	assert.Equal(t, OneOfVariant5{Discriminator: "OneOfVariant5", Id: 654}, v5)
+
+	// discriminator value will be filled by the generated code
+	err = dst.FromOneOfVariant4(OneOfVariant4{Name: "456"})
+	require.NoError(t, err)
+	marshaled, err := json.Marshal(dst)
+	require.NoError(t, err)
+	assertJsonEqual(t, []byte(variant4), marshaled)
+
+	err = dst.FromOneOfVariant5(OneOfVariant5{Id: 654})
+	require.NoError(t, err)
+	marshaled, err = json.Marshal(dst)
+	require.NoError(t, err)
+	assertJsonEqual(t, []byte(variant5), marshaled)
+}
+
 func TestOneOfWithFixedProperties(t *testing.T) {
 	const variant1 = "{\"type\": \"v1\", \"name\": \"123\"}"
 	const variant6 = "{\"type\": \"v6\", \"values\": [1, 2, 3]}"
diff --git a/internal/test/issues/issue-grab_import_names/issue.gen.go b/internal/test/issues/issue-grab_import_names/issue.gen.go
index 6378e57..b9904fc 100644
--- a/internal/test/issues/issue-grab_import_names/issue.gen.go
+++ b/internal/test/issues/issue-grab_import_names/issue.gen.go
@@ -363,12 +363,12 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL
 // Base64 encoded, gzipped, json marshaled Swagger object
 var swaggerSpec = []string{
 
-	"H4sIAAAAAAAC/3yRQWv7MAzFv4rQ2aih/fM/5DjGxu67jTHcVG08YstY6mhX8t2HnZ7KulyERPTz03sX",
-	"HCRmSZxMsb/MDkPaC/YXtGATY49EhA6/uGiQhD121FGHs0PJnHwO2OOGOlqjw+xtrBRc7aUxDmy17FiH",
-	"ErItgAUomYuvk5cd9vjM9iTSEMVHNi6K/dvt5tYr//9HsD0bK8EwBoJBkvHJCHgYhYBLkaIE+2gEh++Q",
-	"CUazTBCE4FMlEVx1b6qKULEj+x0XdJh8rBcvSnQYOfrmxDnXsVoJ6YDz7G51XYkf9UclqDYQlGOyEJlg",
-	"2VOC1j4el7OX7jVEhmOZCE5xIjj7ON2V9eDLn7LeHRbWLEm5hbDuulqaQanl4HOewtCeX1Uv6uw+b3a/",
-	"BDe37ycAAP//wjdd4jYCAAA=",
+	"H4sIAAAAAAAC/3yRzWrrQAyFX0VoPSgmudyFl6W0dN9dKWXiKPEUzw+SUpIGv3uZcVahqTdCwvrm6JwL",
+	"hrTP2F/Qgk2MPRIROvxi0ZAT9thRRx3ODnPh5EvAHjfU0RodFm+j1t3VPjfGga2WHesgodgCWIC5sPg6",
+	"edlhj89sTzk3hPjIxqLYv91ubr3y/38E27OxEgxjIBhyMj4ZAQ9jJmCRLEqwj0Zw+A6FYDQrBCETfGpO",
+	"BFfdm6oiVOzIfseCDpOP9eJFiQ4jR9+cOJc6VpOQDjjP7lbXlfhRf1SCagOBHJOFyATLnhK09vG4nL10",
+	"ryEyHGUiOMWJ4OzjdFfWg5c/Zb07FNaSk3ILYd11tTSDUsvBlzKFoT2/ql7U2X3e7H4Jbm7fTwAAAP//",
+	"VfuleiYCAAA=",
 }
 
 // GetSwagger returns the content of the embedded swagger specification file
diff --git a/internal/test/issues/issue-removed-external-ref/gen/spec_base/issue.gen.go b/internal/test/issues/issue-removed-external-ref/gen/spec_base/issue.gen.go
index 09e8df3..69766e1 100644
--- a/internal/test/issues/issue-removed-external-ref/gen/spec_base/issue.gen.go
+++ b/internal/test/issues/issue-removed-external-ref/gen/spec_base/issue.gen.go
@@ -10,6 +10,7 @@ import (
 	"net/http"
 
 	externalRef0 "github.com/deepmap/oapi-codegen/internal/test/issues/issue-removed-external-ref/gen/spec_ext"
+	"github.com/deepmap/oapi-codegen/pkg/runtime"
 	"github.com/go-chi/chi/v5"
 )
 
@@ -244,9 +245,8 @@ type StrictServerInterface interface {
 	PostNoTrouble(ctx context.Context, request PostNoTroubleRequestObject) (PostNoTroubleResponseObject, error)
 }
 
-type StrictHandlerFunc func(ctx context.Context, w http.ResponseWriter, r *http.Request, args interface{}) (interface{}, error)
-
-type StrictMiddlewareFunc func(f StrictHandlerFunc, operationID string) StrictHandlerFunc
+type StrictHandlerFunc = runtime.StrictHttpHandlerFunc
+type StrictMiddlewareFunc = runtime.StrictHttpMiddlewareFunc
 
 type StrictHTTPServerOptions struct {
 	RequestErrorHandlerFunc  func(w http.ResponseWriter, r *http.Request, err error)
diff --git a/internal/test/issues/issue-removed-external-ref/gen/spec_ext/issue.gen.go b/internal/test/issues/issue-removed-external-ref/gen/spec_ext/issue.gen.go
index 21222f8..ed5a474 100644
--- a/internal/test/issues/issue-removed-external-ref/gen/spec_ext/issue.gen.go
+++ b/internal/test/issues/issue-removed-external-ref/gen/spec_ext/issue.gen.go
@@ -4,10 +4,10 @@
 package spec_ext
 
 import (
-	"context"
 	"fmt"
 	"net/http"
 
+	"github.com/deepmap/oapi-codegen/pkg/runtime"
 	"github.com/go-chi/chi/v5"
 )
 
@@ -161,9 +161,8 @@ type PascalJSONResponse PascalSchema
 type StrictServerInterface interface {
 }
 
-type StrictHandlerFunc func(ctx context.Context, w http.ResponseWriter, r *http.Request, args interface{}) (interface{}, error)
-
-type StrictMiddlewareFunc func(f StrictHandlerFunc, operationID string) StrictHandlerFunc
+type StrictHandlerFunc = runtime.StrictHttpHandlerFunc
+type StrictMiddlewareFunc = runtime.StrictHttpMiddlewareFunc
 
 type StrictHTTPServerOptions struct {
 	RequestErrorHandlerFunc  func(w http.ResponseWriter, r *http.Request, err error)
diff --git a/internal/test/schemas/schemas.gen.go b/internal/test/schemas/schemas.gen.go
index b6a9f20..d1791ab 100644
--- a/internal/test/schemas/schemas.gen.go
+++ b/internal/test/schemas/schemas.gen.go
@@ -48,6 +48,24 @@ type AnyType2 = interface{}
 // CustomStringType defines model for CustomStringType.
 type CustomStringType = string
 
+// DeprecatedProperty defines model for DeprecatedProperty.
+type DeprecatedProperty struct {
+	// NewProp Use this now!
+	NewProp string `json:"newProp"`
+	// Deprecated:
+	OldProp1 *string `json:"oldProp1,omitempty"`
+
+	// OldProp2 It used to do this and that
+	// Deprecated:
+	OldProp2 *string `json:"oldProp2,omitempty"`
+	// Deprecated: Use NewProp instead!
+	OldProp3 *string `json:"oldProp3,omitempty"`
+
+	// OldProp4 It used to do this and that
+	// Deprecated: Use NewProp instead!
+	OldProp4 *string `json:"oldProp4,omitempty"`
+}
+
 // EnumInObjInArray defines model for EnumInObjInArray.
 type EnumInObjInArray = []struct {
 	Val *EnumInObjInArrayVal `json:"val,omitempty"`
@@ -184,6 +202,9 @@ type ClientInterface interface {
 	Issue9WithBody(ctx context.Context, params *Issue9Params, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error)
 
 	Issue9(ctx context.Context, params *Issue9Params, body Issue9JSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error)
+
+	// Issue975 request
+	Issue975(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error)
 }
 
 func (c *Client) EnsureEverythingIsReferenced(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) {
@@ -306,6 +327,18 @@ func (c *Client) Issue9(ctx context.Context, params *Issue9Params, body Issue9JS
 	return c.Client.Do(req)
 }
 
+func (c *Client) Issue975(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) {
+	req, err := NewIssue975Request(c.Server)
+	if err != nil {
+		return nil, err
+	}
+	req = req.WithContext(ctx)
+	if err := c.applyEditors(ctx, req, reqEditors); err != nil {
+		return nil, err
+	}
+	return c.Client.Do(req)
+}
+
 // NewEnsureEverythingIsReferencedRequest generates requests for EnsureEverythingIsReferenced
 func NewEnsureEverythingIsReferencedRequest(server string) (*http.Request, error) {
 	var err error
@@ -585,6 +618,33 @@ func NewIssue9RequestWithBody(server string, params *Issue9Params, contentType s
 	return req, nil
 }
 
+// NewIssue975Request generates requests for Issue975
+func NewIssue975Request(server string) (*http.Request, error) {
+	var err error
+
+	serverURL, err := url.Parse(server)
+	if err != nil {
+		return nil, err
+	}
+
+	operationPath := fmt.Sprintf("/issues/975")
+	if operationPath[0] == '/' {
+		operationPath = "." + operationPath
+	}
+
+	queryURL, err := serverURL.Parse(operationPath)
+	if err != nil {
+		return nil, err
+	}
+
+	req, err := http.NewRequest("GET", queryURL.String(), nil)
+	if err != nil {
+		return nil, err
+	}
+
+	return req, nil
+}
+
 func (c *Client) applyEditors(ctx context.Context, req *http.Request, additionalEditors []RequestEditorFn) error {
 	for _, r := range c.RequestEditors {
 		if err := r(ctx, req); err != nil {
@@ -655,6 +715,9 @@ type ClientWithResponsesInterface interface {
 	Issue9WithBodyWithResponse(ctx context.Context, params *Issue9Params, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*Issue9Response, error)
 
 	Issue9WithResponse(ctx context.Context, params *Issue9Params, body Issue9JSONRequestBody, reqEditors ...RequestEditorFn) (*Issue9Response, error)
+
+	// Issue975 request
+	Issue975WithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*Issue975Response, error)
 }
 
 type EnsureEverythingIsReferencedResponse struct {
@@ -839,6 +902,28 @@ func (r Issue9Response) StatusCode() int {
 	return 0
 }
 
+type Issue975Response struct {
+	Body         []byte
+	HTTPResponse *http.Response
+	JSON200      *DeprecatedProperty
+}
+
+// Status returns HTTPResponse.Status
+func (r Issue975Response) Status() string {
+	if r.HTTPResponse != nil {
+		return r.HTTPResponse.Status
+	}
+	return http.StatusText(0)
+}
+
+// StatusCode returns HTTPResponse.StatusCode
+func (r Issue975Response) StatusCode() int {
+	if r.HTTPResponse != nil {
+		return r.HTTPResponse.StatusCode
+	}
+	return 0
+}
+
 // EnsureEverythingIsReferencedWithResponse request returning *EnsureEverythingIsReferencedResponse
 func (c *ClientWithResponses) EnsureEverythingIsReferencedWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*EnsureEverythingIsReferencedResponse, error) {
 	rsp, err := c.EnsureEverythingIsReferenced(ctx, reqEditors...)
@@ -927,6 +1012,15 @@ func (c *ClientWithResponses) Issue9WithResponse(ctx context.Context, params *Is
 	return ParseIssue9Response(rsp)
 }
 
+// Issue975WithResponse request returning *Issue975Response
+func (c *ClientWithResponses) Issue975WithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*Issue975Response, error) {
+	rsp, err := c.Issue975(ctx, reqEditors...)
+	if err != nil {
+		return nil, err
+	}
+	return ParseIssue975Response(rsp)
+}
+
 // ParseEnsureEverythingIsReferencedResponse parses an HTTP response from a EnsureEverythingIsReferencedWithResponse call
 func ParseEnsureEverythingIsReferencedResponse(rsp *http.Response) (*EnsureEverythingIsReferencedResponse, error) {
 	bodyBytes, err := io.ReadAll(rsp.Body)
@@ -1120,6 +1214,32 @@ func ParseIssue9Response(rsp *http.Response) (*Issue9Response, error) {
 	return response, nil
 }
 
+// ParseIssue975Response parses an HTTP response from a Issue975WithResponse call
+func ParseIssue975Response(rsp *http.Response) (*Issue975Response, error) {
+	bodyBytes, err := io.ReadAll(rsp.Body)
+	defer func() { _ = rsp.Body.Close() }()
+	if err != nil {
+		return nil, err
+	}
+
+	response := &Issue975Response{
+		Body:         bodyBytes,
+		HTTPResponse: rsp,
+	}
+
+	switch {
+	case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200:
+		var dest DeprecatedProperty
+		if err := json.Unmarshal(bodyBytes, &dest); err != nil {
+			return nil, err
+		}
+		response.JSON200 = &dest
+
+	}
+
+	return response, nil
+}
+
 // ServerInterface represents all server handlers.
 type ServerInterface interface {
 
@@ -1146,6 +1266,9 @@ type ServerInterface interface {
 
 	// (GET /issues/9)
 	Issue9(ctx echo.Context, params Issue9Params) error
+
+	// (GET /issues/975)
+	Issue975(ctx echo.Context) error
 }
 
 // ServerInterfaceWrapper converts echo contexts to parameters.
@@ -1157,7 +1280,7 @@ type ServerInterfaceWrapper struct {
 func (w *ServerInterfaceWrapper) EnsureEverythingIsReferenced(ctx echo.Context) error {
 	var err error
 
-	ctx.Set(Access_tokenScopes, []string{""})
+	ctx.Set(Access_tokenScopes, []string{})
 
 	// Invoke the callback with all the unmarshalled arguments
 	err = w.Handler.EnsureEverythingIsReferenced(ctx)
@@ -1168,7 +1291,7 @@ func (w *ServerInterfaceWrapper) EnsureEverythingIsReferenced(ctx echo.Context)
 func (w *ServerInterfaceWrapper) Issue127(ctx echo.Context) error {
 	var err error
 
-	ctx.Set(Access_tokenScopes, []string{""})
+	ctx.Set(Access_tokenScopes, []string{})
 
 	// Invoke the callback with all the unmarshalled arguments
 	err = w.Handler.Issue127(ctx)
@@ -1179,7 +1302,7 @@ func (w *ServerInterfaceWrapper) Issue127(ctx echo.Context) error {
 func (w *ServerInterfaceWrapper) Issue185(ctx echo.Context) error {
 	var err error
 
-	ctx.Set(Access_tokenScopes, []string{""})
+	ctx.Set(Access_tokenScopes, []string{})
 
 	// Invoke the callback with all the unmarshalled arguments
 	err = w.Handler.Issue185(ctx)
@@ -1197,7 +1320,7 @@ func (w *ServerInterfaceWrapper) Issue209(ctx echo.Context) error {
 		return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter str: %s", err))
 	}
 
-	ctx.Set(Access_tokenScopes, []string{""})
+	ctx.Set(Access_tokenScopes, []string{})
 
 	// Invoke the callback with all the unmarshalled arguments
 	err = w.Handler.Issue209(ctx, str)
@@ -1215,7 +1338,7 @@ func (w *ServerInterfaceWrapper) Issue30(ctx echo.Context) error {
 		return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter fallthrough: %s", err))
 	}
 
-	ctx.Set(Access_tokenScopes, []string{""})
+	ctx.Set(Access_tokenScopes, []string{})
 
 	// Invoke the callback with all the unmarshalled arguments
 	err = w.Handler.Issue30(ctx, pFallthrough)
@@ -1226,7 +1349,7 @@ func (w *ServerInterfaceWrapper) Issue30(ctx echo.Context) error {
 func (w *ServerInterfaceWrapper) GetIssues375(ctx echo.Context) error {
 	var err error
 
-	ctx.Set(Access_tokenScopes, []string{""})
+	ctx.Set(Access_tokenScopes, []string{})
 
 	// Invoke the callback with all the unmarshalled arguments
 	err = w.Handler.GetIssues375(ctx)
@@ -1244,7 +1367,7 @@ func (w *ServerInterfaceWrapper) Issue41(ctx echo.Context) error {
 		return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter 1param: %s", err))
 	}
 
-	ctx.Set(Access_tokenScopes, []string{""})
+	ctx.Set(Access_tokenScopes, []string{})
 
 	// Invoke the callback with all the unmarshalled arguments
 	err = w.Handler.Issue41(ctx, n1param)
@@ -1255,7 +1378,7 @@ func (w *ServerInterfaceWrapper) Issue41(ctx echo.Context) error {
 func (w *ServerInterfaceWrapper) Issue9(ctx echo.Context) error {
 	var err error
 
-	ctx.Set(Access_tokenScopes, []string{""})
+	ctx.Set(Access_tokenScopes, []string{})
 
 	// Parameter object where we will unmarshal all parameters from the context
 	var params Issue9Params
@@ -1271,6 +1394,17 @@ func (w *ServerInterfaceWrapper) Issue9(ctx echo.Context) error {
 	return err
 }
 
+// Issue975 converts echo context to params.
+func (w *ServerInterfaceWrapper) Issue975(ctx echo.Context) error {
+	var err error
+
+	ctx.Set(Access_tokenScopes, []string{})
+
+	// Invoke the callback with all the unmarshalled arguments
+	err = w.Handler.Issue975(ctx)
+	return err
+}
+
 // This is a simple interface which specifies echo.Route addition functions which
 // are present on both echo.Echo and echo.Group, since we want to allow using
 // either of them for path registration
@@ -1307,33 +1441,37 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL
 	router.GET(baseURL+"/issues/375", wrapper.GetIssues375)
 	router.GET(baseURL+"/issues/41/:1param", wrapper.Issue41)
 	router.GET(baseURL+"/issues/9", wrapper.Issue9)
+	router.GET(baseURL+"/issues/975", wrapper.Issue975)
 
 }
 
 // Base64 encoded, gzipped, json marshaled Swagger object
 var swaggerSpec = []string{
 
-	"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",
+	"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",
+	"7tMAMZKIRc6LEVfE8H8FAAD//5edhkCXEgAA",
 }
 
 // GetSwagger returns the content of the embedded swagger specification file
diff --git a/internal/test/schemas/schemas.yaml b/internal/test/schemas/schemas.yaml
index 3d73527..319faa7 100644
--- a/internal/test/schemas/schemas.yaml
+++ b/internal/test/schemas/schemas.yaml
@@ -121,6 +121,19 @@ paths:
             application/json:
               schema:
                 $ref: "#/components/schemas/EnumInObjInArray"
+  /issues/975:
+    get:
+      operationId: Issue975
+      description: |
+        Deprecated fields should get a proper comment
+      responses:
+        200:
+          description: A struct with deprecated fields with varying level of documentation
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/DeprecatedProperty"
+
 components:
   schemas:
     GenericObject:
@@ -165,6 +178,32 @@ components:
             enum:
               - first
               - second
+    DeprecatedProperty:
+      type: object
+      required:
+        - newProp
+        - oldProp
+      properties:
+        newProp:
+          type: string
+          description: Use this now!
+        oldProp1:
+          type: string
+          deprecated: true
+          # description: No description on this one to test generation in that case
+        oldProp2:
+          type: string
+          deprecated: true
+          description: It used to do this and that
+        oldProp3:
+          type: string
+          deprecated: true
+          x-deprecated-reason: Use NewProp instead!
+        oldProp4:
+          type: string
+          deprecated: true
+          x-deprecated-reason: Use NewProp instead!
+          description: It used to do this and that
   parameters:
     StringInPath:
       name: str
@@ -183,4 +222,3 @@ components:
         JWT-format access token.
 security:
   - access-token: [ ]
-
diff --git a/internal/test/strict-server/chi/server.gen.go b/internal/test/strict-server/chi/server.gen.go
index 124c057..b3904b5 100644
--- a/internal/test/strict-server/chi/server.gen.go
+++ b/internal/test/strict-server/chi/server.gen.go
@@ -34,6 +34,9 @@ type ServerInterface interface {
 	// (POST /multiple)
 	MultipleRequestAndResponseTypes(w http.ResponseWriter, r *http.Request)
 
+	// (GET /reserved-go-keyword-parameters/{type})
+	ReservedGoKeywordParameters(w http.ResponseWriter, r *http.Request, pType string)
+
 	// (POST /reusable-responses)
 	ReusableResponses(w http.ResponseWriter, r *http.Request)
 
@@ -107,6 +110,32 @@ func (siw *ServerInterfaceWrapper) MultipleRequestAndResponseTypes(w http.Respon
 	handler.ServeHTTP(w, r.WithContext(ctx))
 }
 
+// ReservedGoKeywordParameters operation middleware
+func (siw *ServerInterfaceWrapper) ReservedGoKeywordParameters(w http.ResponseWriter, r *http.Request) {
+	ctx := r.Context()
+
+	var err error
+
+	// ------------- Path parameter "type" -------------
+	var pType string
+
+	err = runtime.BindStyledParameterWithLocation("simple", false, "type", runtime.ParamLocationPath, chi.URLParam(r, "type"), &pType)
+	if err != nil {
+		siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "type", Err: err})
+		return
+	}
+
+	var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		siw.Handler.ReservedGoKeywordParameters(w, r, pType)
+	})
+
+	for _, middleware := range siw.HandlerMiddlewares {
+		handler = middleware(handler)
+	}
+
+	handler.ServeHTTP(w, r.WithContext(ctx))
+}
+
 // ReusableResponses operation middleware
 func (siw *ServerInterfaceWrapper) ReusableResponses(w http.ResponseWriter, r *http.Request) {
 	ctx := r.Context()
@@ -368,6 +397,9 @@ func HandlerWithOptions(si ServerInterface, options ChiServerOptions) http.Handl
 	r.Group(func(r chi.Router) {
 		r.Post(options.BaseURL+"/multiple", wrapper.MultipleRequestAndResponseTypes)
 	})
+	r.Group(func(r chi.Router) {
+		r.Get(options.BaseURL+"/reserved-go-keyword-parameters/{type}", wrapper.ReservedGoKeywordParameters)
+	})
 	r.Group(func(r chi.Router) {
 		r.Post(options.BaseURL+"/reusable-responses", wrapper.ReusableResponses)
 	})
@@ -553,6 +585,24 @@ func (response MultipleRequestAndResponseTypes400Response) VisitMultipleRequestA
 	return nil
 }
 
+type ReservedGoKeywordParametersRequestObject struct {
+	Type string `json:"type"`
+}
+
+type ReservedGoKeywordParametersResponseObject interface {
+	VisitReservedGoKeywordParametersResponse(w http.ResponseWriter) error
+}
+
+type ReservedGoKeywordParameters200TextResponse string
+
+func (response ReservedGoKeywordParameters200TextResponse) VisitReservedGoKeywordParametersResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", "text/plain")
+	w.WriteHeader(200)
+
+	_, err := w.Write([]byte(response))
+	return err
+}
+
 type ReusableResponsesRequestObject struct {
 	Body *ReusableResponsesJSONRequestBody
 }
@@ -820,6 +870,9 @@ type StrictServerInterface interface {
 	// (POST /multiple)
 	MultipleRequestAndResponseTypes(ctx context.Context, request MultipleRequestAndResponseTypesRequestObject) (MultipleRequestAndResponseTypesResponseObject, error)
 
+	// (GET /reserved-go-keyword-parameters/{type})
+	ReservedGoKeywordParameters(ctx context.Context, request ReservedGoKeywordParametersRequestObject) (ReservedGoKeywordParametersResponseObject, error)
+
 	// (POST /reusable-responses)
 	ReusableResponses(ctx context.Context, request ReusableResponsesRequestObject) (ReusableResponsesResponseObject, error)
 
@@ -839,9 +892,8 @@ type StrictServerInterface interface {
 	HeadersExample(ctx context.Context, request HeadersExampleRequestObject) (HeadersExampleResponseObject, error)
 }
 
-type StrictHandlerFunc func(ctx context.Context, w http.ResponseWriter, r *http.Request, args interface{}) (interface{}, error)
-
-type StrictMiddlewareFunc func(f StrictHandlerFunc, operationID string) StrictHandlerFunc
+type StrictHandlerFunc = runtime.StrictHttpHandlerFunc
+type StrictMiddlewareFunc = runtime.StrictHttpMiddlewareFunc
 
 type StrictHTTPServerOptions struct {
 	RequestErrorHandlerFunc  func(w http.ResponseWriter, r *http.Request, err error)
@@ -996,6 +1048,32 @@ func (sh *strictHandler) MultipleRequestAndResponseTypes(w http.ResponseWriter,
 	}
 }
 
+// ReservedGoKeywordParameters operation middleware
+func (sh *strictHandler) ReservedGoKeywordParameters(w http.ResponseWriter, r *http.Request, pType string) {
+	var request ReservedGoKeywordParametersRequestObject
+
+	request.Type = pType
+
+	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) {
+		return sh.ssi.ReservedGoKeywordParameters(ctx, request.(ReservedGoKeywordParametersRequestObject))
+	}
+	for _, middleware := range sh.middlewares {
+		handler = middleware(handler, "ReservedGoKeywordParameters")
+	}
+
+	response, err := handler(r.Context(), w, r, request)
+
+	if err != nil {
+		sh.options.ResponseErrorHandlerFunc(w, r, err)
+	} else if validResponse, ok := response.(ReservedGoKeywordParametersResponseObject); ok {
+		if err := validResponse.VisitReservedGoKeywordParametersResponse(w); err != nil {
+			sh.options.ResponseErrorHandlerFunc(w, r, err)
+		}
+	} else if response != nil {
+		sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", response))
+	}
+}
+
 // ReusableResponses operation middleware
 func (sh *strictHandler) ReusableResponses(w http.ResponseWriter, r *http.Request) {
 	var request ReusableResponsesRequestObject
@@ -1184,21 +1262,23 @@ func (sh *strictHandler) HeadersExample(w http.ResponseWriter, r *http.Request,
 // Base64 encoded, gzipped, json marshaled Swagger object
 var swaggerSpec = []string{
 
-	"H4sIAAAAAAAC/+xYS4/iOBD+K1btnkaB0D194rbTGmnfI9Ezp9UcirgAzya2166QRoj/vnJsaBjSCFo8",
-	"pNXeEqde/qq+KsdLKExljSbNHoZLcOSt0Z7alzFKR//U5Dm8SfKFU5aV0TCEDyhH6dsqA0e1x3FJa/Ug",
-	"XxjNpFtVtLZUBQbV/JsP+kvwxYwqDE8/OprAEH7IX0LJ41ef0zNWtiRYrVbZdxF8+g0ymBFKcm208fFu",
-	"1zYvLMEQPDulpxCMRLH7TjGlmabkgrcgmoIIAus4hkuwzlhyrCJGcyxr6vaUVsz4GxUcd6D0xOxj+Wg0",
-	"o9JeSDWZkCPNIoEngg0vfG2tcUxSjBcieChYeHJzcpABKw6BwdP2ukgBe8hgTs5HR3f9QX8Q8mUsabQK",
-	"hvC+XcrAIs/aDW0SZE1X3n99+vSnUF5gzaZCVgWW5UJU6PwMy5KkUJpNiLEu2PehdeXazP8ik/rHhGUo",
-	"m7aCPhi5uETFtIW5Vc/3g8GVCnOVwUN01mVjE1S+xbDWzATrsgP0L/pvbRotyDnj0s7yqi5ZWXS8naxd",
-	"tP9YixwD+cZePjGu6klkvBDq5/J0U+BTM+gkydPMNF7MTCPYCElYikbxTKwVv2O30gKFV3paklgHlXVm",
-	"sqTUc3/ScpT28jnYuDiXsh0rz72maXpt8mpXki6MJPk2s6rCKeVWT3fVg21kGMJ4waFs97vrmYooA6Zn",
-	"zm2JSh8eHVdqJ/8jfTZiR7quzya9neR1E3dNKi8K1GIc+DjxgcRdvvZIOkqeRlsStxlxhzHaO61do2uG",
-	"5L8+qT7T81FD6oxkvXY1ngpYHRdfxyxpHQPbG7l/BIpzJcnklX040fLNQPWWCjVRJHtpF70Y22st4dHo",
-	"whHvDu1wAtaGxcZYOJjzjEREIBPeiIZEVXsWFr0XitsuUqp4uJe01zy+vET2GD2FyX5EVt9dKKfvbpXR",
-	"h8Hd6SrvL1w3O8P3FT6Ofv8YZU79wznblD/xjHI+vzeiczhW97buALop/HMUeJnpBak5SYFaCkdcO01S",
-	"zBWuf1v3uJkMvKTVosOKuPX61xLCCEkXC5CBxoo273epCJQLyLKrKTt0PXHQ1j1kh+4svv6Hf6gvedNz",
-	"6TpdZRAvZWKx1K4MGWW2wzyPlzl93+B0Sq6vTI5Wwerr6t8AAAD//ygSomqZEwAA",
+	"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",
+	"AP//O0NNuucUAAA=",
 }
 
 // GetSwagger returns the content of the embedded swagger specification file
diff --git a/internal/test/strict-server/chi/server.go b/internal/test/strict-server/chi/server.go
index 5b70268..b0724db 100644
--- a/internal/test/strict-server/chi/server.go
+++ b/internal/test/strict-server/chi/server.go
@@ -100,3 +100,7 @@ func (s StrictServer) HeadersExample(ctx context.Context, request HeadersExample
 func (s StrictServer) ReusableResponses(ctx context.Context, request ReusableResponsesRequestObject) (ReusableResponsesResponseObject, error) {
 	return ReusableResponses200JSONResponse{ReusableresponseJSONResponse: ReusableresponseJSONResponse{Body: *request.Body}}, nil
 }
+
+func (s StrictServer) ReservedGoKeywordParameters(ctx context.Context, request ReservedGoKeywordParametersRequestObject) (ReservedGoKeywordParametersResponseObject, error) {
+	return ReservedGoKeywordParameters200TextResponse(""), nil
+}
diff --git a/internal/test/strict-server/client/client.gen.go b/internal/test/strict-server/client/client.gen.go
index 68105f2..5ec0210 100644
--- a/internal/test/strict-server/client/client.gen.go
+++ b/internal/test/strict-server/client/client.gen.go
@@ -156,6 +156,9 @@ type ClientInterface interface {
 
 	MultipleRequestAndResponseTypesWithTextBody(ctx context.Context, body MultipleRequestAndResponseTypesTextRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error)
 
+	// ReservedGoKeywordParameters request
+	ReservedGoKeywordParameters(ctx context.Context, pType string, reqEditors ...RequestEditorFn) (*http.Response, error)
+
 	// ReusableResponses request with any body
 	ReusableResponsesWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error)
 
@@ -267,6 +270,18 @@ func (c *Client) MultipleRequestAndResponseTypesWithTextBody(ctx context.Context
 	return c.Client.Do(req)
 }
 
+func (c *Client) ReservedGoKeywordParameters(ctx context.Context, pType string, reqEditors ...RequestEditorFn) (*http.Response, error) {
+	req, err := NewReservedGoKeywordParametersRequest(c.Server, pType)
+	if err != nil {
+		return nil, err
+	}
+	req = req.WithContext(ctx)
+	if err := c.applyEditors(ctx, req, reqEditors); err != nil {
+		return nil, err
+	}
+	return c.Client.Do(req)
+}
+
 func (c *Client) ReusableResponsesWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) {
 	req, err := NewReusableResponsesRequestWithBody(c.Server, contentType, body)
 	if err != nil {
@@ -514,6 +529,40 @@ func NewMultipleRequestAndResponseTypesRequestWithBody(server string, contentTyp
 	return req, nil
 }
 
+// NewReservedGoKeywordParametersRequest generates requests for ReservedGoKeywordParameters
+func NewReservedGoKeywordParametersRequest(server string, pType string) (*http.Request, error) {
+	var err error
+
+	var pathParam0 string
+
+	pathParam0, err = runtime.StyleParamWithLocation("simple", false, "type", runtime.ParamLocationPath, pType)
+	if err != nil {
+		return nil, err
+	}
+
+	serverURL, err := url.Parse(server)
+	if err != nil {
+		return nil, err
+	}
+
+	operationPath := fmt.Sprintf("/reserved-go-keyword-parameters/%s", pathParam0)
+	if operationPath[0] == '/' {
+		operationPath = "." + operationPath
+	}
+
+	queryURL, err := serverURL.Parse(operationPath)
+	if err != nil {
+		return nil, err
+	}
+
+	req, err := http.NewRequest("GET", queryURL.String(), nil)
+	if err != nil {
+		return nil, err
+	}
+
+	return req, nil
+}
+
 // NewReusableResponsesRequest calls the generic ReusableResponses builder with application/json body
 func NewReusableResponsesRequest(server string, body ReusableResponsesJSONRequestBody) (*http.Request, error) {
 	var bodyReader io.Reader
@@ -808,6 +857,9 @@ type ClientWithResponsesInterface interface {
 
 	MultipleRequestAndResponseTypesWithTextBodyWithResponse(ctx context.Context, body MultipleRequestAndResponseTypesTextRequestBody, reqEditors ...RequestEditorFn) (*MultipleRequestAndResponseTypesResponse, error)
 
+	// ReservedGoKeywordParameters request
+	ReservedGoKeywordParametersWithResponse(ctx context.Context, pType string, reqEditors ...RequestEditorFn) (*ReservedGoKeywordParametersResponse, error)
+
 	// ReusableResponses request with any body
 	ReusableResponsesWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*ReusableResponsesResponse, error)
 
@@ -900,6 +952,27 @@ func (r MultipleRequestAndResponseTypesResponse) StatusCode() int {
 	return 0
 }
 
+type ReservedGoKeywordParametersResponse struct {
+	Body         []byte
+	HTTPResponse *http.Response
+}
+
+// Status returns HTTPResponse.Status
+func (r ReservedGoKeywordParametersResponse) Status() string {
+	if r.HTTPResponse != nil {
+		return r.HTTPResponse.Status
+	}
+	return http.StatusText(0)
+}
+
+// StatusCode returns HTTPResponse.StatusCode
+func (r ReservedGoKeywordParametersResponse) StatusCode() int {
+	if r.HTTPResponse != nil {
+		return r.HTTPResponse.StatusCode
+	}
+	return 0
+}
+
 type ReusableResponsesResponse struct {
 	Body         []byte
 	HTTPResponse *http.Response
@@ -1087,6 +1160,15 @@ func (c *ClientWithResponses) MultipleRequestAndResponseTypesWithTextBodyWithRes
 	return ParseMultipleRequestAndResponseTypesResponse(rsp)
 }
 
+// ReservedGoKeywordParametersWithResponse request returning *ReservedGoKeywordParametersResponse
+func (c *ClientWithResponses) ReservedGoKeywordParametersWithResponse(ctx context.Context, pType string, reqEditors ...RequestEditorFn) (*ReservedGoKeywordParametersResponse, error) {
+	rsp, err := c.ReservedGoKeywordParameters(ctx, pType, reqEditors...)
+	if err != nil {
+		return nil, err
+	}
+	return ParseReservedGoKeywordParametersResponse(rsp)
+}
+
 // ReusableResponsesWithBodyWithResponse request with arbitrary body returning *ReusableResponsesResponse
 func (c *ClientWithResponses) ReusableResponsesWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*ReusableResponsesResponse, error) {
 	rsp, err := c.ReusableResponsesWithBody(ctx, contentType, body, reqEditors...)
@@ -1244,6 +1326,22 @@ func ParseMultipleRequestAndResponseTypesResponse(rsp *http.Response) (*Multiple
 	return response, nil
 }
 
+// ParseReservedGoKeywordParametersResponse parses an HTTP response from a ReservedGoKeywordParametersWithResponse call
+func ParseReservedGoKeywordParametersResponse(rsp *http.Response) (*ReservedGoKeywordParametersResponse, error) {
+	bodyBytes, err := io.ReadAll(rsp.Body)
+	defer func() { _ = rsp.Body.Close() }()
+	if err != nil {
+		return nil, err
+	}
+
+	response := &ReservedGoKeywordParametersResponse{
+		Body:         bodyBytes,
+		HTTPResponse: rsp,
+	}
+
+	return response, nil
+}
+
 // ParseReusableResponsesResponse parses an HTTP response from a ReusableResponsesWithResponse call
 func ParseReusableResponsesResponse(rsp *http.Response) (*ReusableResponsesResponse, error) {
 	bodyBytes, err := io.ReadAll(rsp.Body)
diff --git a/internal/test/strict-server/echo/server.gen.go b/internal/test/strict-server/echo/server.gen.go
index 46531bd..0912230 100644
--- a/internal/test/strict-server/echo/server.gen.go
+++ b/internal/test/strict-server/echo/server.gen.go
@@ -34,6 +34,9 @@ type ServerInterface interface {
 	// (POST /multiple)
 	MultipleRequestAndResponseTypes(ctx echo.Context) error
 
+	// (GET /reserved-go-keyword-parameters/{type})
+	ReservedGoKeywordParameters(ctx echo.Context, pType string) error
+
 	// (POST /reusable-responses)
 	ReusableResponses(ctx echo.Context) error
 
@@ -85,6 +88,22 @@ func (w *ServerInterfaceWrapper) MultipleRequestAndResponseTypes(ctx echo.Contex
 	return err
 }
 
+// ReservedGoKeywordParameters converts echo context to params.
+func (w *ServerInterfaceWrapper) ReservedGoKeywordParameters(ctx echo.Context) error {
+	var err error
+	// ------------- Path parameter "type" -------------
+	var pType string
+
+	err = runtime.BindStyledParameterWithLocation("simple", false, "type", runtime.ParamLocationPath, ctx.Param("type"), &pType)
+	if err != nil {
+		return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter type: %s", err))
+	}
+
+	// Invoke the callback with all the unmarshalled arguments
+	err = w.Handler.ReservedGoKeywordParameters(ctx, pType)
+	return err
+}
+
 // ReusableResponses converts echo context to params.
 func (w *ServerInterfaceWrapper) ReusableResponses(ctx echo.Context) error {
 	var err error
@@ -207,6 +226,7 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL
 	router.POST(baseURL+"/json", wrapper.JSONExample)
 	router.POST(baseURL+"/multipart", wrapper.MultipartExample)
 	router.POST(baseURL+"/multiple", wrapper.MultipleRequestAndResponseTypes)
+	router.GET(baseURL+"/reserved-go-keyword-parameters/:type", wrapper.ReservedGoKeywordParameters)
 	router.POST(baseURL+"/reusable-responses", wrapper.ReusableResponses)
 	router.POST(baseURL+"/text", wrapper.TextExample)
 	router.POST(baseURL+"/unknown", wrapper.UnknownExample)
@@ -379,6 +399,24 @@ func (response MultipleRequestAndResponseTypes400Response) VisitMultipleRequestA
 	return nil
 }
 
+type ReservedGoKeywordParametersRequestObject struct {
+	Type string `json:"type"`
+}
+
+type ReservedGoKeywordParametersResponseObject interface {
+	VisitReservedGoKeywordParametersResponse(w http.ResponseWriter) error
+}
+
+type ReservedGoKeywordParameters200TextResponse string
+
+func (response ReservedGoKeywordParameters200TextResponse) VisitReservedGoKeywordParametersResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", "text/plain")
+	w.WriteHeader(200)
+
+	_, err := w.Write([]byte(response))
+	return err
+}
+
 type ReusableResponsesRequestObject struct {
 	Body *ReusableResponsesJSONRequestBody
 }
@@ -646,6 +684,9 @@ type StrictServerInterface interface {
 	// (POST /multiple)
 	MultipleRequestAndResponseTypes(ctx context.Context, request MultipleRequestAndResponseTypesRequestObject) (MultipleRequestAndResponseTypesResponseObject, error)
 
+	// (GET /reserved-go-keyword-parameters/{type})
+	ReservedGoKeywordParameters(ctx context.Context, request ReservedGoKeywordParametersRequestObject) (ReservedGoKeywordParametersResponseObject, error)
+
 	// (POST /reusable-responses)
 	ReusableResponses(ctx context.Context, request ReusableResponsesRequestObject) (ReusableResponsesResponseObject, error)
 
@@ -665,9 +706,8 @@ type StrictServerInterface interface {
 	HeadersExample(ctx context.Context, request HeadersExampleRequestObject) (HeadersExampleResponseObject, error)
 }
 
-type StrictHandlerFunc func(ctx echo.Context, args interface{}) (interface{}, error)
-
-type StrictMiddlewareFunc func(f StrictHandlerFunc, operationID string) StrictHandlerFunc
+type StrictHandlerFunc = runtime.StrictEchoHandlerFunc
+type StrictMiddlewareFunc = runtime.StrictEchoMiddlewareFunc
 
 func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc) ServerInterface {
 	return &strictHandler{ssi: ssi, middlewares: middlewares}
@@ -796,6 +836,31 @@ func (sh *strictHandler) MultipleRequestAndResponseTypes(ctx echo.Context) error
 	return nil
 }
 
+// ReservedGoKeywordParameters operation middleware
+func (sh *strictHandler) ReservedGoKeywordParameters(ctx echo.Context, pType string) error {
+	var request ReservedGoKeywordParametersRequestObject
+
+	request.Type = pType
+
+	handler := func(ctx echo.Context, request interface{}) (interface{}, error) {
+		return sh.ssi.ReservedGoKeywordParameters(ctx.Request().Context(), request.(ReservedGoKeywordParametersRequestObject))
+	}
+	for _, middleware := range sh.middlewares {
+		handler = middleware(handler, "ReservedGoKeywordParameters")
+	}
+
+	response, err := handler(ctx, request)
+
+	if err != nil {
+		return err
+	} else if validResponse, ok := response.(ReservedGoKeywordParametersResponseObject); ok {
+		return validResponse.VisitReservedGoKeywordParametersResponse(ctx.Response())
+	} else if response != nil {
+		return fmt.Errorf("Unexpected response type: %T", response)
+	}
+	return nil
+}
+
 // ReusableResponses operation middleware
 func (sh *strictHandler) ReusableResponses(ctx echo.Context) error {
 	var request ReusableResponsesRequestObject
@@ -974,21 +1039,23 @@ func (sh *strictHandler) HeadersExample(ctx echo.Context, params HeadersExampleP
 // Base64 encoded, gzipped, json marshaled Swagger object
 var swaggerSpec = []string{
 
-	"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",
+	"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",
+	"AP//O0NNuucUAAA=",
 }
 
 // GetSwagger returns the content of the embedded swagger specification file
diff --git a/internal/test/strict-server/echo/server.go b/internal/test/strict-server/echo/server.go
index 5b70268..b0724db 100644
--- a/internal/test/strict-server/echo/server.go
+++ b/internal/test/strict-server/echo/server.go
@@ -100,3 +100,7 @@ func (s StrictServer) HeadersExample(ctx context.Context, request HeadersExample
 func (s StrictServer) ReusableResponses(ctx context.Context, request ReusableResponsesRequestObject) (ReusableResponsesResponseObject, error) {
 	return ReusableResponses200JSONResponse{ReusableresponseJSONResponse: ReusableresponseJSONResponse{Body: *request.Body}}, nil
 }
+
+func (s StrictServer) ReservedGoKeywordParameters(ctx context.Context, request ReservedGoKeywordParametersRequestObject) (ReservedGoKeywordParametersResponseObject, error) {
+	return ReservedGoKeywordParameters200TextResponse(""), nil
+}
diff --git a/internal/test/strict-server/gin/server.gen.go b/internal/test/strict-server/gin/server.gen.go
index 81b9aef..dcac415 100644
--- a/internal/test/strict-server/gin/server.gen.go
+++ b/internal/test/strict-server/gin/server.gen.go
@@ -34,6 +34,9 @@ type ServerInterface interface {
 	// (POST /multiple)
 	MultipleRequestAndResponseTypes(c *gin.Context)
 
+	// (GET /reserved-go-keyword-parameters/{type})
+	ReservedGoKeywordParameters(c *gin.Context, pType string)
+
 	// (POST /reusable-responses)
 	ReusableResponses(c *gin.Context)
 
@@ -101,6 +104,30 @@ func (siw *ServerInterfaceWrapper) MultipleRequestAndResponseTypes(c *gin.Contex
 	siw.Handler.MultipleRequestAndResponseTypes(c)
 }
 
+// ReservedGoKeywordParameters operation middleware
+func (siw *ServerInterfaceWrapper) ReservedGoKeywordParameters(c *gin.Context) {
+
+	var err error
+
+	// ------------- Path parameter "type" -------------
+	var pType string
+
+	err = runtime.BindStyledParameter("simple", false, "type", c.Param("type"), &pType)
+	if err != nil {
+		siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter type: %s", err), http.StatusBadRequest)
+		return
+	}
+
+	for _, middleware := range siw.HandlerMiddlewares {
+		middleware(c)
+		if c.IsAborted() {
+			return
+		}
+	}
+
+	siw.Handler.ReservedGoKeywordParameters(c, pType)
+}
+
 // ReusableResponses operation middleware
 func (siw *ServerInterfaceWrapper) ReusableResponses(c *gin.Context) {
 
@@ -257,6 +284,7 @@ func RegisterHandlersWithOptions(router gin.IRouter, si ServerInterface, options
 	router.POST(options.BaseURL+"/json", wrapper.JSONExample)
 	router.POST(options.BaseURL+"/multipart", wrapper.MultipartExample)
 	router.POST(options.BaseURL+"/multiple", wrapper.MultipleRequestAndResponseTypes)
+	router.GET(options.BaseURL+"/reserved-go-keyword-parameters/:type", wrapper.ReservedGoKeywordParameters)
 	router.POST(options.BaseURL+"/reusable-responses", wrapper.ReusableResponses)
 	router.POST(options.BaseURL+"/text", wrapper.TextExample)
 	router.POST(options.BaseURL+"/unknown", wrapper.UnknownExample)
@@ -428,6 +456,24 @@ func (response MultipleRequestAndResponseTypes400Response) VisitMultipleRequestA
 	return nil
 }
 
+type ReservedGoKeywordParametersRequestObject struct {
+	Type string `json:"type"`
+}
+
+type ReservedGoKeywordParametersResponseObject interface {
+	VisitReservedGoKeywordParametersResponse(w http.ResponseWriter) error
+}
+
+type ReservedGoKeywordParameters200TextResponse string
+
+func (response ReservedGoKeywordParameters200TextResponse) VisitReservedGoKeywordParametersResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", "text/plain")
+	w.WriteHeader(200)
+
+	_, err := w.Write([]byte(response))
+	return err
+}
+
 type ReusableResponsesRequestObject struct {
 	Body *ReusableResponsesJSONRequestBody
 }
@@ -695,6 +741,9 @@ type StrictServerInterface interface {
 	// (POST /multiple)
 	MultipleRequestAndResponseTypes(ctx context.Context, request MultipleRequestAndResponseTypesRequestObject) (MultipleRequestAndResponseTypesResponseObject, error)
 
+	// (GET /reserved-go-keyword-parameters/{type})
+	ReservedGoKeywordParameters(ctx context.Context, request ReservedGoKeywordParametersRequestObject) (ReservedGoKeywordParametersResponseObject, error)
+
 	// (POST /reusable-responses)
 	ReusableResponses(ctx context.Context, request ReusableResponsesRequestObject) (ReusableResponsesResponseObject, error)
 
@@ -714,9 +763,8 @@ type StrictServerInterface interface {
 	HeadersExample(ctx context.Context, request HeadersExampleRequestObject) (HeadersExampleResponseObject, error)
 }
 
-type StrictHandlerFunc func(ctx *gin.Context, args interface{}) (interface{}, error)
-
-type StrictMiddlewareFunc func(f StrictHandlerFunc, operationID string) StrictHandlerFunc
+type StrictHandlerFunc = runtime.StrictGinHandlerFunc
+type StrictMiddlewareFunc = runtime.StrictGinMiddlewareFunc
 
 func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc) ServerInterface {
 	return &strictHandler{ssi: ssi, middlewares: middlewares}
@@ -750,6 +798,7 @@ func (sh *strictHandler) JSONExample(ctx *gin.Context) {
 
 	if err != nil {
 		ctx.Error(err)
+		ctx.Status(http.StatusInternalServerError)
 	} else if validResponse, ok := response.(JSONExampleResponseObject); ok {
 		if err := validResponse.VisitJSONExampleResponse(ctx.Writer); err != nil {
 			ctx.Error(err)
@@ -781,6 +830,7 @@ func (sh *strictHandler) MultipartExample(ctx *gin.Context) {
 
 	if err != nil {
 		ctx.Error(err)
+		ctx.Status(http.StatusInternalServerError)
 	} else if validResponse, ok := response.(MultipartExampleResponseObject); ok {
 		if err := validResponse.VisitMultipartExampleResponse(ctx.Writer); err != nil {
 			ctx.Error(err)
@@ -847,6 +897,7 @@ func (sh *strictHandler) MultipleRequestAndResponseTypes(ctx *gin.Context) {
 
 	if err != nil {
 		ctx.Error(err)
+		ctx.Status(http.StatusInternalServerError)
 	} else if validResponse, ok := response.(MultipleRequestAndResponseTypesResponseObject); ok {
 		if err := validResponse.VisitMultipleRequestAndResponseTypesResponse(ctx.Writer); err != nil {
 			ctx.Error(err)
@@ -856,6 +907,33 @@ func (sh *strictHandler) MultipleRequestAndResponseTypes(ctx *gin.Context) {
 	}
 }
 
+// ReservedGoKeywordParameters operation middleware
+func (sh *strictHandler) ReservedGoKeywordParameters(ctx *gin.Context, pType string) {
+	var request ReservedGoKeywordParametersRequestObject
+
+	request.Type = pType
+
+	handler := func(ctx *gin.Context, request interface{}) (interface{}, error) {
+		return sh.ssi.ReservedGoKeywordParameters(ctx, request.(ReservedGoKeywordParametersRequestObject))
+	}
+	for _, middleware := range sh.middlewares {
+		handler = middleware(handler, "ReservedGoKeywordParameters")
+	}
+
+	response, err := handler(ctx, request)
+
+	if err != nil {
+		ctx.Error(err)
+		ctx.Status(http.StatusInternalServerError)
+	} else if validResponse, ok := response.(ReservedGoKeywordParametersResponseObject); ok {
+		if err := validResponse.VisitReservedGoKeywordParametersResponse(ctx.Writer); err != nil {
+			ctx.Error(err)
+		}
+	} else if response != nil {
+		ctx.Error(fmt.Errorf("Unexpected response type: %T", response))
+	}
+}
+
 // ReusableResponses operation middleware
 func (sh *strictHandler) ReusableResponses(ctx *gin.Context) {
 	var request ReusableResponsesRequestObject
@@ -879,6 +957,7 @@ func (sh *strictHandler) ReusableResponses(ctx *gin.Context) {
 
 	if err != nil {
 		ctx.Error(err)
+		ctx.Status(http.StatusInternalServerError)
 	} else if validResponse, ok := response.(ReusableResponsesResponseObject); ok {
 		if err := validResponse.VisitReusableResponsesResponse(ctx.Writer); err != nil {
 			ctx.Error(err)
@@ -911,6 +990,7 @@ func (sh *strictHandler) TextExample(ctx *gin.Context) {
 
 	if err != nil {
 		ctx.Error(err)
+		ctx.Status(http.StatusInternalServerError)
 	} else if validResponse, ok := response.(TextExampleResponseObject); ok {
 		if err := validResponse.VisitTextExampleResponse(ctx.Writer); err != nil {
 			ctx.Error(err)
@@ -937,6 +1017,7 @@ func (sh *strictHandler) UnknownExample(ctx *gin.Context) {
 
 	if err != nil {
 		ctx.Error(err)
+		ctx.Status(http.StatusInternalServerError)
 	} else if validResponse, ok := response.(UnknownExampleResponseObject); ok {
 		if err := validResponse.VisitUnknownExampleResponse(ctx.Writer); err != nil {
 			ctx.Error(err)
@@ -965,6 +1046,7 @@ func (sh *strictHandler) UnspecifiedContentType(ctx *gin.Context) {
 
 	if err != nil {
 		ctx.Error(err)
+		ctx.Status(http.StatusInternalServerError)
 	} else if validResponse, ok := response.(UnspecifiedContentTypeResponseObject); ok {
 		if err := validResponse.VisitUnspecifiedContentTypeResponse(ctx.Writer); err != nil {
 			ctx.Error(err)
@@ -1000,6 +1082,7 @@ func (sh *strictHandler) URLEncodedExample(ctx *gin.Context) {
 
 	if err != nil {
 		ctx.Error(err)
+		ctx.Status(http.StatusInternalServerError)
 	} else if validResponse, ok := response.(URLEncodedExampleResponseObject); ok {
 		if err := validResponse.VisitURLEncodedExampleResponse(ctx.Writer); err != nil {
 			ctx.Error(err)
@@ -1034,6 +1117,7 @@ func (sh *strictHandler) HeadersExample(ctx *gin.Context, params HeadersExampleP
 
 	if err != nil {
 		ctx.Error(err)
+		ctx.Status(http.StatusInternalServerError)
 	} else if validResponse, ok := response.(HeadersExampleResponseObject); ok {
 		if err := validResponse.VisitHeadersExampleResponse(ctx.Writer); err != nil {
 			ctx.Error(err)
@@ -1046,21 +1130,23 @@ func (sh *strictHandler) HeadersExample(ctx *gin.Context, params HeadersExampleP
 // Base64 encoded, gzipped, json marshaled Swagger object
 var swaggerSpec = []string{
 
-	"H4sIAAAAAAAC/+xYS4/iOBD+K1btnkaB0D194rbTGmnfI9Ezp9UcirgAzya2166QRoj/vnJsaBjSCFo8",
-	"pNXeEqde/qq+KsdLKExljSbNHoZLcOSt0Z7alzFKR//U5Dm8SfKFU5aV0TCEDyhH6dsqA0e1x3FJa/Ug",
-	"XxjNpFtVtLZUBQbV/JsP+kvwxYwqDE8/OprAEH7IX0LJ41ef0zNWtiRYrVbZdxF8+g0ymBFKcm208fFu",
-	"1zYvLMEQPDulpxCMRLH7TjGlmabkgrcgmoIIAus4hkuwzlhyrCJGcyxr6vaUVsz4GxUcd6D0xOxj+Wg0",
-	"o9JeSDWZkCPNIoEngg0vfG2tcUxSjBcieChYeHJzcpABKw6BwdP2ukgBe8hgTs5HR3f9QX8Q8mUsabQK",
-	"hvC+XcrAIs/aDW0SZE1X3n99+vSnUF5gzaZCVgWW5UJU6PwMy5KkUJpNiLEu2PehdeXazP8ik/rHhGUo",
-	"m7aCPhi5uETFtIW5Vc/3g8GVCnOVwUN01mVjE1S+xbDWzATrsgP0L/pvbRotyDnj0s7yqi5ZWXS8naxd",
-	"tP9YixwD+cZePjGu6klkvBDq5/J0U+BTM+gkydPMNF7MTCPYCElYikbxTKwVv2O30gKFV3paklgHlXVm",
-	"sqTUc3/ScpT28jnYuDiXsh0rz72maXpt8mpXki6MJPk2s6rCKeVWT3fVg21kGMJ4waFs97vrmYooA6Zn",
-	"zm2JSh8eHVdqJ/8jfTZiR7quzya9neR1E3dNKi8K1GIc+DjxgcRdvvZIOkqeRlsStxlxhzHaO61do2uG",
-	"5L8+qT7T81FD6oxkvXY1ngpYHRdfxyxpHQPbG7l/BIpzJcnklX040fLNQPWWCjVRJHtpF70Y22st4dHo",
-	"whHvDu1wAtaGxcZYOJjzjEREIBPeiIZEVXsWFr0XitsuUqp4uJe01zy+vET2GD2FyX5EVt9dKKfvbpXR",
-	"h8Hd6SrvL1w3O8P3FT6Ofv8YZU79wznblD/xjHI+vzeiczhW97buALop/HMUeJnpBak5SYFaCkdcO01S",
-	"zBWuf1v3uJkMvKTVosOKuPX61xLCCEkXC5CBxoo273epCJQLyLKrKTt0PXHQ1j1kh+4svv6Hf6gvedNz",
-	"6TpdZRAvZWKx1K4MGWW2wzyPlzl93+B0Sq6vTI5Wwerr6t8AAAD//ygSomqZEwAA",
+	"H4sIAAAAAAAC/+xYX2/bNhD/KgS3p0KynDRPeluDotu6rYOTPg15oMWzzFYiuePJimHouw8UJf+pFS/O",
+	"7BgY+mbRd787/u4Pj1zxzJTWaNDkeLriCM4a7aD9mAqJ8HcFjvyXBJehsqSM5il/J+Sk+6+JOELlxLSA",
+	"Xt3LZ0YT6FZVWFuoTHjV5Ivz+ivusjmUwv/6EWHGU/5DsnElCf+6BB5FaQvgTdNE33jw6SOP+ByEBGy9",
+	"DT+vdrFpaYGn3BEqnXMPEsSuB8WUJsgBvTUv2jnhBXo/0hW3aCwgqcDRQhQVDFvqVsz0C2QUdqD0zOxz",
+	"eWs0CaUdk2o2AwRNrCOPeQzHXGWtQQLJpkvmLWTEHOACkEecFHnH+N32OuscdjziC0AXDF2NxqOxj5ex",
+	"oIVVPOVv26WIW0HzdkPrAFkzFPdf7z79wZRjoiJTClKZKIolKwW6uSgKkExpMt7HKiM34q0pbCP/i+zU",
+	"33dc+rRpM+idkctzZEybmFv5fD0ev1JiNhG/CcaGMNZOJVsV1sLMRFUMkP5Zf9Wm1gwQDXY7S8qqIGUF",
+	"0nawdtn+vRd5DuVrvGRmsIylIHEm1k9l6aLEd81gsEju5qZ2bG5qRoZJEAWrFc1Zr/hNdSvNBHNK5wWw",
+	"3qloMJIFdD33Jy0n3V7uPcbZaynaQXmM67qO2+BVWIDOjAT5MlhVihwSq/NddY8tiKd8uiSftvvd9URJ",
+	"FHGCR0psIZQ+fHS8Ujv5zvTJCjuUK0J7JMo4N/FXWNYGZWwFihII0CUrb73xwDkMlPKfa0mWCc2mwLQo",
+	"QTIxI0D2wbAO0u2V7KSz+8F8DCIbqPa8XX+kf624p6Q9g3nEvQGeBlZCXSv0QSesIDpA28O/5ud/CkDP",
+	"Zpj04h1Tw22wb1Fr6hBmzrfEocgN8BcsTbYkLjMwHM64vdn3Nc4gH8mnz/17eHzWkX/C1vfatX0sYVVY",
+	"fJqzTus5tL2wkz6DxYWSYJLS3hyJfDFSnYVMzRTIuNtFHHx7qiXcGp0h0O4I5O8T2hBbg/lrDs2BBQYi",
+	"5gyrgZWVI2aFc0xR20UKFa5KEvaax+eNZ7fB0v2mnR6K6pszxfTNpSJ6M746XuXtmfNmZ5R5oh4nv70P",
+	"MsfeF082Mx058Z3O7oXK2V9S4q0XleES/jkIbM70DNTCT0RaMgSqUINkCyX6R4C92uwANmEdmoWCG5tp",
+	"qH/dOWYgig5iXfPo0AvQw//4eeKc72bnztMm4uGJKyRLhYWPKJFNkyQ8jY1cLfIccKRMIqzizUPzTwAA",
+	"AP//O0NNuucUAAA=",
 }
 
 // GetSwagger returns the content of the embedded swagger specification file
diff --git a/internal/test/strict-server/gin/server.go b/internal/test/strict-server/gin/server.go
index 5b70268..b0724db 100644
--- a/internal/test/strict-server/gin/server.go
+++ b/internal/test/strict-server/gin/server.go
@@ -100,3 +100,7 @@ func (s StrictServer) HeadersExample(ctx context.Context, request HeadersExample
 func (s StrictServer) ReusableResponses(ctx context.Context, request ReusableResponsesRequestObject) (ReusableResponsesResponseObject, error) {
 	return ReusableResponses200JSONResponse{ReusableresponseJSONResponse: ReusableresponseJSONResponse{Body: *request.Body}}, nil
 }
+
+func (s StrictServer) ReservedGoKeywordParameters(ctx context.Context, request ReservedGoKeywordParametersRequestObject) (ReservedGoKeywordParametersResponseObject, error) {
+	return ReservedGoKeywordParameters200TextResponse(""), nil
+}
diff --git a/internal/test/strict-server/strict-schema.yaml b/internal/test/strict-server/strict-schema.yaml
index a9a2c41..da0ed07 100644
--- a/internal/test/strict-server/strict-schema.yaml
+++ b/internal/test/strict-server/strict-schema.yaml
@@ -228,6 +228,23 @@ paths:
           $ref: "#/components/responses/badrequest"
         default:
           description: Unknown error
+  /reserved-go-keyword-parameters/{type}:
+    get:
+        operationId: ReservedGoKeywordParameters
+        description: Parameters can be named after Go keywords
+        parameters:
+          - name: type
+            in: path
+            required: true
+            schema:
+                type: string
+        responses:
+          200:
+            description: OK
+            content:
+              text/plain:
+                schema:
+                  type: string
 components:
   responses:
     badrequest:
diff --git a/pkg/codegen/codegen_test.go b/pkg/codegen/codegen_test.go
index e3878f5..499174b 100644
--- a/pkg/codegen/codegen_test.go
+++ b/pkg/codegen/codegen_test.go
@@ -145,8 +145,11 @@ func TestExampleOpenAPICodeGeneration(t *testing.T) {
 		},
 	}
 
+	loader := openapi3.NewLoader()
+	loader.IsExternalRefsAllowed = true
+
 	// Get a spec from the test definition in this file:
-	swagger, err := openapi3.NewLoader().LoadFromData([]byte(testOpenAPIDefinition))
+	swagger, err := loader.LoadFromData([]byte(testOpenAPIDefinition))
 	assert.NoError(t, err)
 
 	// Run our code generation:
@@ -198,6 +201,49 @@ type GetTestByNameResponse struct {
 	checkLint(t, "test.gen.go", []byte(code))
 }
 
+// Validate any types nested under AdditionalPropertiesTypes is propagated up as with normal Property AdditionalTypes
+func TestExampleOpenAPICodeGenerationSchemaAdditionalPropertyTypes(t *testing.T) {
+
+	// Input vars for code generation:
+	packageName := "testswagger"
+	opts := Configuration{
+		PackageName: packageName,
+		Generate: GenerateOptions{
+			EchoServer:   false,
+			Client:       false,
+			Models:       true,
+			EmbeddedSpec: false,
+		},
+	}
+
+	loader := openapi3.NewLoader()
+	loader.IsExternalRefsAllowed = true
+
+	// Get a spec from the test definition in this file:
+	swagger, err := loader.LoadFromData([]byte(testSchemaArrayTypes))
+	assert.NoError(t, err)
+
+	// Run our code generation:
+	code, err := Generate(swagger, opts)
+	assert.NoError(t, err)
+	assert.NotEmpty(t, code)
+
+	// Check that we have valid (formattable) code:
+	_, err = format.Source([]byte(code))
+	assert.NoError(t, err)
+
+	// Check that we have a package:
+	assert.Contains(t, code, "package testswagger")
+
+	// Check that AdditionalPropertyTypes structs are propagated up properly:
+	assert.Contains(t, code, "[]PatchedBulkWritableCircuitTerminationRequest_Relationships_Destination_Objects_Item")
+	assert.Contains(t, code, "type PatchedBulkWritableCircuitTerminationRequest_Relationships_Destination_Objects_Item struct {")
+	assert.Contains(t, code, "[]BulkWritableCircuitTerminationRequest_Relationships_Destination_Objects_Item")
+	assert.Contains(t, code, "type BulkWritableCircuitTerminationRequest_Relationships_Destination_Objects_Item struct {")
+	assert.Contains(t, code, "[]WritableCircuitTerminationRequest_Relationships_Destination_Objects_Item ")
+	assert.Contains(t, code, "type WritableCircuitTerminationRequest_Relationships_Destination_Objects_Item struct {")
+}
+
 func TestGoTypeImport(t *testing.T) {
 	packageName := "api"
 	opts := Configuration{
@@ -306,5 +352,8 @@ func (t *ExampleSchema_Item) FromExternalRef0NewPet(v externalRef0.NewPet) error
 
 }
 
+//go:embed test_schema_additional_properties_types.yaml
+var testSchemaArrayTypes string
+
 //go:embed test_spec.yaml
 var testOpenAPIDefinition string
diff --git a/pkg/codegen/extension_test.go b/pkg/codegen/extension_test.go
index 64681a6..1d5a215 100644
--- a/pkg/codegen/extension_test.go
+++ b/pkg/codegen/extension_test.go
@@ -9,7 +9,7 @@ import (
 
 func Test_extTypeName(t *testing.T) {
 	type args struct {
-		extPropValue interface{}
+		extPropValue json.RawMessage
 	}
 	tests := []struct {
 		name    string
@@ -24,21 +24,27 @@ func Test_extTypeName(t *testing.T) {
 			wantErr: false,
 		},
 		{
-			name:    "type conversion error",
+			name:    "nil conversion error",
 			args:    args{nil},
 			want:    "",
 			wantErr: true,
 		},
 		{
-			name:    "json unmarshal error",
-			args:    args{json.RawMessage("invalid json format")},
+			name:    "type conversion error",
+			args:    args{json.RawMessage(`12`)},
 			want:    "",
 			wantErr: true,
 		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			got, err := extTypeName(tt.args.extPropValue)
+			// kin-openapi no longer returns these as RawMessage
+			var extPropValue interface{}
+			if tt.args.extPropValue != nil {
+				err := json.Unmarshal(tt.args.extPropValue, &extPropValue)
+				assert.NoError(t, err)
+			}
+			got, err := extTypeName(extPropValue)
 			if tt.wantErr {
 				assert.Error(t, err)
 				return
diff --git a/pkg/codegen/filter_test.go b/pkg/codegen/filter_test.go
index d3a5aec..774d016 100644
--- a/pkg/codegen/filter_test.go
+++ b/pkg/codegen/filter_test.go
@@ -23,8 +23,11 @@ func TestFilterOperationsByTag(t *testing.T) {
 			},
 		}
 
+		loader := openapi3.NewLoader()
+		loader.IsExternalRefsAllowed = true
+
 		// Get a spec from the test definition in this file:
-		swagger, err := openapi3.NewLoader().LoadFromData([]byte(testOpenAPIDefinition))
+		swagger, err := loader.LoadFromData([]byte(testOpenAPIDefinition))
 		assert.NoError(t, err)
 
 		// Run our code generation:
@@ -49,8 +52,11 @@ func TestFilterOperationsByTag(t *testing.T) {
 			},
 		}
 
+		loader := openapi3.NewLoader()
+		loader.IsExternalRefsAllowed = true
+
 		// Get a spec from the test definition in this file:
-		swagger, err := openapi3.NewLoader().LoadFromData([]byte(testOpenAPIDefinition))
+		swagger, err := loader.LoadFromData([]byte(testOpenAPIDefinition))
 		assert.NoError(t, err)
 
 		// Run our code generation:
diff --git a/pkg/codegen/operations_test.go b/pkg/codegen/operations_test.go
index 0eff03e..77a54a8 100644
--- a/pkg/codegen/operations_test.go
+++ b/pkg/codegen/operations_test.go
@@ -131,7 +131,7 @@ func TestGenerateDefaultOperationID(t *testing.T) {
 	}
 
 	for _, test := range suite {
-		got, err := generateDefaultOperationID(test.op, test.path)
+		got, err := generateDefaultOperationID(test.op, test.path, ToCamelCase)
 		if err != nil {
 			if !test.wantErr {
 				t.Fatalf("did not expected error but got %v", err)
diff --git a/pkg/codegen/test_schema.json b/pkg/codegen/test_schema.json
new file mode 100644
index 0000000..d649394
--- /dev/null
+++ b/pkg/codegen/test_schema.json
@@ -0,0 +1,15 @@
+{
+  "title": "node",
+  "type": "object",
+  "description": "Represents a node",
+  "properties": {
+    "id": {
+      "type": "string",
+      "format": "uri-reference"
+    },
+    "type": {
+      "type": "string",
+      "pattern": "^[A-Z][a-zA-Z0-9]*$"
+    }
+  }
+}
\ No newline at end of file
diff --git a/pkg/codegen/test_schema_additional_properties_types.yaml b/pkg/codegen/test_schema_additional_properties_types.yaml
new file mode 100644
index 0000000..0cbf800
--- /dev/null
+++ b/pkg/codegen/test_schema_additional_properties_types.yaml
@@ -0,0 +1,513 @@
+openapi: 3.0.3
+info:
+  title: API Documentation
+  version: 1.5.7 (1.3)
+  description: Source of truth and network automation platform
+  license:
+    name: Apache v2 License
+paths:
+  /circuits/circuit-terminations/:
+    post:
+      operationId: circuits_circuit_terminations_create
+      description: |-
+        Base class to use for API ViewSets based on OrganizationalModel or PrimaryModel.
+
+        Can also be used for models derived from BaseModel, so long as they support Notes.
+      tags:
+        - circuits
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: "#/components/schemas/WritableCircuitTerminationRequest"
+        required: true
+      security:
+        - cookieAuth: []
+        - tokenAuth: []
+      responses:
+        "201":
+          content:
+            application/json; version=1.3:
+              schema:
+                $ref: "#/components/schemas/CircuitTermination"
+          description: ""
+    put:
+      operationId: circuits_circuit_terminations_bulk_update
+      description: |-
+        Base class to use for API ViewSets based on OrganizationalModel or PrimaryModel.
+
+        Can also be used for models derived from BaseModel, so long as they support Notes.
+      tags:
+        - circuits
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: array
+              items:
+                $ref: "#/components/schemas/BulkWritableCircuitTerminationRequest"
+        required: true
+      security:
+        - cookieAuth: []
+        - tokenAuth: []
+      responses:
+        "200":
+          content:
+            application/json; version=1.3:
+              schema:
+                type: array
+                items:
+                  $ref: "#/components/schemas/CircuitTermination"
+          description: ""
+    patch:
+      operationId: circuits_circuit_terminations_bulk_partial_update
+      description: |-
+        Base class to use for API ViewSets based on OrganizationalModel or PrimaryModel.
+
+        Can also be used for models derived from BaseModel, so long as they support Notes.
+      tags:
+        - circuits
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: array
+              items:
+                $ref: "#/components/schemas/PatchedBulkWritableCircuitTerminationRequest"
+        required: true
+      security:
+        - cookieAuth: []
+        - tokenAuth: []
+      responses:
+        "200":
+          content:
+            application/json; version=1.3:
+              schema:
+                type: array
+                items:
+                  $ref: "#/components/schemas/CircuitTermination"
+          description: ""
+components:
+  schemas:
+    CircuitTermination:
+      type: object
+      description: |-
+        Base class to use for serializers based on OrganizationalModel or PrimaryModel.
+
+        Can also be used for models derived from BaseModel, so long as they support custom fields and relationships.
+      properties:
+        id:
+          type: string
+          format: uuid
+          readOnly: true
+        display:
+          type: string
+          readOnly: true
+          description: Human friendly display value
+        url:
+          type: string
+          format: uri
+          readOnly: true
+        description:
+          type: string
+          maxLength: 200
+      required:
+        - display
+        - id
+        - url
+    WritableCircuitTerminationRequest:
+      type: object
+      description: |-
+        Base class to use for serializers based on OrganizationalModel or PrimaryModel.
+
+        Can also be used for models derived from BaseModel, so long as they support custom fields and relationships.
+      properties:
+        circuit:
+          type: string
+          format: uuid
+        site:
+          type: string
+          format: uuid
+          nullable: true
+        location:
+          type: string
+          format: uuid
+          nullable: true
+        provider_network:
+          type: string
+          format: uuid
+          nullable: true
+        description:
+          type: string
+          maxLength: 200
+        custom_fields:
+          type: object
+          additionalProperties: {}
+        relationships:
+          type: object
+          additionalProperties:
+            type: object
+            required:
+              - id
+              - url
+              - name
+              - type
+            properties:
+              id:
+                type: string
+                format: uuid
+                readOnly: true
+              url:
+                type: string
+                format: uri
+                readOnly: true
+              name:
+                type: string
+                readOnly: true
+              type:
+                type: string
+                readOnly: true
+                example: one-to-many
+              source:
+                type: object
+                properties:
+                  label:
+                    type: string
+                    readOnly: true
+                  object_type:
+                    type: string
+                    readOnly: true
+                    example: dcim.site
+                  objects:
+                    type: array
+                    items:
+                      type: object
+                      properties:
+                        id:
+                          type: string
+                          format: uuid
+                        url:
+                          type: string
+                          format: uri
+                          readOnly: true
+                        display:
+                          type: string
+                          readOnly: true
+                      additionalProperties: true
+              destination:
+                type: object
+                properties:
+                  label:
+                    type: string
+                    readOnly: true
+                  object_type:
+                    type: string
+                    readOnly: true
+                    example: dcim.site
+                  objects:
+                    type: array
+                    items:
+                      type: object
+                      properties:
+                        id:
+                          type: string
+                          format: uuid
+                        url:
+                          type: string
+                          format: uri
+                          readOnly: true
+                        display:
+                          type: string
+                          readOnly: true
+                      additionalProperties: true
+              peer:
+                type: object
+                properties:
+                  label:
+                    type: string
+                    readOnly: true
+                  object_type:
+                    type: string
+                    readOnly: true
+                    example: dcim.site
+                  objects:
+                    type: array
+                    items:
+                      type: object
+                      properties:
+                        id:
+                          type: string
+                          format: uuid
+                        url:
+                          type: string
+                          format: uri
+                          readOnly: true
+                        display:
+                          type: string
+                          readOnly: true
+                      additionalProperties: true
+      required:
+        - circuit
+    BulkWritableCircuitTerminationRequest:
+      type: object
+      description: |-
+        Base class to use for serializers based on OrganizationalModel or PrimaryModel.
+
+        Can also be used for models derived from BaseModel, so long as they support custom fields and relationships.
+      properties:
+        id:
+          type: string
+          format: uuid
+        description:
+          type: string
+          maxLength: 200
+        custom_fields:
+          type: object
+          additionalProperties: true
+        relationships:
+          type: object
+          additionalProperties:
+            type: object
+            required:
+              - id
+              - url
+              - name
+              - type
+            properties:
+              id:
+                type: string
+                format: uuid
+                readOnly: true
+              url:
+                type: string
+                format: uri
+                readOnly: true
+              name:
+                type: string
+                readOnly: true
+              type:
+                type: string
+                readOnly: true
+                example: one-to-many
+              source:
+                type: object
+                properties:
+                  label:
+                    type: string
+                    readOnly: true
+                  object_type:
+                    type: string
+                    readOnly: true
+                    example: dcim.site
+                  objects:
+                    type: array
+                    items:
+                      type: object
+                      properties:
+                        id:
+                          type: string
+                          format: uuid
+                        url:
+                          type: string
+                          format: uri
+                          readOnly: true
+                        display:
+                          type: string
+                          readOnly: true
+                      additionalProperties: true
+              destination:
+                type: object
+                properties:
+                  label:
+                    type: string
+                    readOnly: true
+                  object_type:
+                    type: string
+                    readOnly: true
+                    example: dcim.site
+                  objects:
+                    type: array
+                    items:
+                      type: object
+                      properties:
+                        id:
+                          type: string
+                          format: uuid
+                        url:
+                          type: string
+                          format: uri
+                          readOnly: true
+                        display:
+                          type: string
+                          readOnly: true
+                      additionalProperties: true
+              peer:
+                type: object
+                properties:
+                  label:
+                    type: string
+                    readOnly: true
+                  object_type:
+                    type: string
+                    readOnly: true
+                    example: dcim.site
+                  objects:
+                    type: array
+                    items:
+                      type: object
+                      properties:
+                        id:
+                          type: string
+                          format: uuid
+                        url:
+                          type: string
+                          format: uri
+                          readOnly: true
+                        display:
+                          type: string
+                          readOnly: true
+                      additionalProperties: true
+      required:
+        - id
+    PatchedBulkWritableCircuitTerminationRequest:
+      type: object
+      description: |-
+        Base class to use for serializers based on OrganizationalModel or PrimaryModel.
+
+        Can also be used for models derived from BaseModel, so long as they support custom fields and relationships.
+      properties:
+        id:
+          type: string
+          format: uuid
+        port_speed:
+          type: integer
+          maximum: 2147483647
+          minimum: 0
+          nullable: true
+          title: Port speed (Kbps)
+        upstream_speed:
+          type: integer
+          maximum: 2147483647
+          minimum: 0
+          nullable: true
+          title: Upstream speed (Kbps)
+          description: Upstream speed, if different from port speed
+        xconnect_id:
+          type: string
+          title: Cross-connect ID
+          maxLength: 50
+        pp_info:
+          type: string
+          title: Patch panel/port(s)
+          maxLength: 100
+        description:
+          type: string
+          maxLength: 200
+        custom_fields:
+          type: object
+          additionalProperties: {}
+        relationships:
+          type: object
+          additionalProperties:
+            type: object
+            required:
+              - id
+              - url
+              - name
+              - type
+            properties:
+              id:
+                type: string
+                format: uuid
+                readOnly: true
+              url:
+                type: string
+                format: uri
+                readOnly: true
+              name:
+                type: string
+                readOnly: true
+              type:
+                type: string
+                readOnly: true
+                example: one-to-many
+              source:
+                type: object
+                properties:
+                  label:
+                    type: string
+                    readOnly: true
+                  object_type:
+                    type: string
+                    readOnly: true
+                    example: dcim.site
+                  objects:
+                    type: array
+                    items:
+                      type: object
+                      properties:
+                        id:
+                          type: string
+                          format: uuid
+                        url:
+                          type: string
+                          format: uri
+                          readOnly: true
+                        display:
+                          type: string
+                          readOnly: true
+                      additionalProperties: true
+              destination:
+                type: object
+                properties:
+                  label:
+                    type: string
+                    readOnly: true
+                  object_type:
+                    type: string
+                    readOnly: true
+                    example: dcim.site
+                  objects:
+                    type: array
+                    items:
+                      type: object
+                      properties:
+                        id:
+                          type: string
+                          format: uuid
+                        url:
+                          type: string
+                          format: uri
+                          readOnly: true
+                        display:
+                          type: string
+                          readOnly: true
+                      additionalProperties: true
+              peer:
+                type: object
+                properties:
+                  label:
+                    type: string
+                    readOnly: true
+                  object_type:
+                    type: string
+                    readOnly: true
+                    example: dcim.site
+                  objects:
+                    type: array
+                    items:
+                      type: object
+                      properties:
+                        id:
+                          type: string
+                          format: uuid
+                        url:
+                          type: string
+                          format: uri
+                          readOnly: true
+                        display:
+                          type: string
+                          readOnly: true
+                      additionalProperties: true
+      required:
+        - id
diff --git a/pkg/codegen/test_spec.yaml b/pkg/codegen/test_spec.yaml
index 7491c69..b50f749 100644
--- a/pkg/codegen/test_spec.yaml
+++ b/pkg/codegen/test_spec.yaml
@@ -108,6 +108,25 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/Error'
+  /user:
+    get:
+      tags:
+        - mergeAllOf
+      summary: Merges allOf ref-ing a JSON schema
+      operationId: getUser
+      responses:
+        200:
+          description: Success
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/User'
+        default:
+          description: Error
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/Error'
 
 components:
   schemas:
@@ -177,3 +196,12 @@ components:
             - na
             - single
             - double
+    User:
+      allOf:
+        - $ref: ./test_schema.json
+        - type: object
+          additionalProperties: false
+          properties:
+            name:
+              type: string
+              description: User name
diff --git a/pkg/codegen/utils_test.go b/pkg/codegen/utils_test.go
index 518e287..644167a 100644
--- a/pkg/codegen/utils_test.go
+++ b/pkg/codegen/utils_test.go
@@ -432,3 +432,71 @@ func TestSchemaNameToTypeName(t *testing.T) {
 		assert.Equal(t, want, SchemaNameToTypeName(in))
 	}
 }
+
+
+func TestTypeDefinitionsEquivalent(t *testing.T) {
+	def1 := TypeDefinition{TypeName: "name", Schema: Schema{
+		OAPISchema: &openapi3.Schema{},
+	}}
+	def2 := TypeDefinition{TypeName: "name", Schema: Schema{
+		OAPISchema: &openapi3.Schema{},
+	}}
+	assert.True(t, TypeDefinitionsEquivalent(def1, def2))
+}
+
+
+func TestRefPathToObjName(t *testing.T) {
+	t.Parallel()
+
+	for in, want := range map[string]string{
+		"#/components/schemas/Foo":                         "Foo",
+		"#/components/parameters/Bar":                      "Bar",
+		"#/components/responses/baz_baz":                   "baz_baz",
+		"document.json#/Foo":                               "Foo",
+		"http://deepmap.com/schemas/document.json#/objObj": "objObj",
+	} {
+		assert.Equal(t, want, RefPathToObjName(in))
+	}
+}
+
+func Test_replaceInitialisms(t *testing.T) {
+	type args struct {
+		s string
+	}
+	tests := []struct {
+		name string
+		args args
+		want string
+	}{
+		{
+			name: "empty string",
+			args: args{s: ""},
+			want: "",
+		},
+		{
+			name: "no initialism",
+			args: args{s: "foo"},
+			want: "foo",
+		},
+		{
+			name: "one initialism",
+			args: args{s: "fooId"},
+			want: "fooID",
+		},
+		{
+			name: "two initialism",
+			args: args{s: "fooIdBarApi"},
+			want: "fooIDBarAPI",
+		},
+		{
+			name: "already initialism",
+			args: args{s: "fooIDBarAPI"},
+			want: "fooIDBarAPI",
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			assert.Equalf(t, tt.want, replaceInitialism(tt.args.s), "replaceInitialism(%v)", tt.args.s)
+		})
+	}
+}
diff --git a/pkg/runtime/deepobject_test.go b/pkg/runtime/deepobject_test.go
index d1a5a16..237673a 100644
--- a/pkg/runtime/deepobject_test.go
+++ b/pkg/runtime/deepobject_test.go
@@ -17,18 +17,20 @@ type InnerObject struct {
 
 // These are all possible field types, mandatory and optional.
 type AllFields struct {
-	I   int          `json:"i"`
-	Oi  *int         `json:"oi,omitempty"`
-	F   float32      `json:"f"`
-	Of  *float32     `json:"of,omitempty"`
-	B   bool         `json:"b"`
-	Ob  *bool        `json:"ob,omitempty"`
-	As  []string     `json:"as"`
-	Oas *[]string    `json:"oas,omitempty"`
-	O   InnerObject  `json:"o"`
-	Oo  *InnerObject `json:"oo,omitempty"`
-	D   MockBinder   `json:"d"`
-	Od  *MockBinder  `json:"od,omitempty"`
+	I   int             `json:"i"`
+	Oi  *int            `json:"oi,omitempty"`
+	F   float32         `json:"f"`
+	Of  *float32        `json:"of,omitempty"`
+	B   bool            `json:"b"`
+	Ob  *bool           `json:"ob,omitempty"`
+	As  []string        `json:"as"`
+	Oas *[]string       `json:"oas,omitempty"`
+	O   InnerObject     `json:"o"`
+	Oo  *InnerObject    `json:"oo,omitempty"`
+	D   MockBinder      `json:"d"`
+	Od  *MockBinder     `json:"od,omitempty"`
+	M   map[string]int  `json:"m"`
+	Om  *map[string]int `json:"om,omitempty"`
 }
 
 func TestDeepObject(t *testing.T) {
@@ -40,6 +42,9 @@ func TestDeepObject(t *testing.T) {
 		Name: "Marcin Romaszewicz",
 		ID:   123,
 	}
+	om := map[string]int{
+		"additional": 1,
+	}
 	d := MockBinder{Time: time.Date(2020, 2, 1, 0, 0, 0, 0, time.UTC)}
 
 	srcObj := AllFields{
@@ -58,6 +63,8 @@ func TestDeepObject(t *testing.T) {
 		Oo: &oo,
 		D:  d,
 		Od: &d,
+		M:  om,
+		Om: &om,
 	}
 
 	marshaled, err := MarshalDeepObject(srcObj, "p")