Skip to main content

spec v0.5.0 — OpenAPI 3.2, Validation Severity, and a Rebuilt Core

· 4 min read
Oaswrap Maintainer

Today we're shipping spec v0.5.0. This is the biggest release since the project started — a rebuilt generator core, first-class OpenAPI 3.2.0 support, structured validation with severity levels, a new Iris adapter, and several quality-of-life improvements. There are also a few breaking changes to be aware of.

OpenAPI 3.2.0 support

spec now supports the full range of OpenAPI versions from 3.0.0 through 3.2.0. Set your target version with WithOpenAPIVersion:

import "github.com/oaswrap/spec/openapi"

r := spec.NewRouter(
option.WithOpenAPIVersion(openapi.Version320),
option.WithTitle("My API"),
)

OpenAPI 3.2 brings meaningful additions to the spec model. The ones you can use directly in v0.5.0:

Querystring parameters — model the entire query string as a single typed parameter using the new Query route method and the querystring struct tag:

type SearchQuery struct {
Q string `querystring:"q" mediaType:"application/x-www-form-urlencoded"`
Lang string `querystring:"lang"`
}

r.Query("/search", option.Summary("Search"))

Tag hierarchiesTagParent and TagKind let you organize tags into a parent/child tree, which UI tools that support OAS 3.2 can render as grouped operation collections:

r := spec.NewRouter(
option.WithOpenAPIVersion(openapi.Version320),
option.WithTag("users", option.TagKind("group")),
option.WithTag("users.list", option.TagParent("users")),
option.WithTag("users.create", option.TagParent("users")),
)

Schema dialect and $self — use WithJSONSchemaDialect and WithSelf to set the root JSON Schema dialect URI and the document's own identifier, both required by some 3.2 validators.

Version-specific validation is also tightened in this release — the validator now checks OAS version constraints and will surface errors when 3.0-only constructs appear in a 3.1+ spec, and vice versa.

Structured validation with severity levels

Previously, Validate() returned a single yes/no result. That's still there, but v0.5.0 adds ValidateReport() — a structured report with three severity levels: Error, Warning, and Info.

if err := r.ValidateReport(); err != nil {
fmt.Println(err) // includes all findings grouped by severity
}

Errors are hard failures (invalid spec). Warnings cover patterns that are technically valid but likely wrong — missing operation IDs, undeclared path parameters, ambiguous security schemes. Info items are best-practice hints that won't break anything but are worth addressing.

ValidateReport is available on the core router and on all adapters. If you only want to fail on hard errors, continue using Validate(). If you want the full picture, switch to ValidateReport().

New Iris adapter

spec now supports Iris, adding a ninth framework adapter to the roster. Install it with:

go get github.com/oaswrap/spec/adapter/irisopenapi
import (
"github.com/kataras/iris/v12"
"github.com/oaswrap/spec/adapter/irisopenapi"
)

app := iris.New()
api := irisopenapi.NewRouter(app,
option.WithTitle("My API"),
option.WithVersion("1.0.0"),
)

api.Get("/users/{id}", func(ctx iris.Context) {
// handler
}, option.Summary("Get user"), option.Response(200, new(User)))

The full adapter list is now: chi, echo (v4 and v5), fiber (v2 and v3), gin, gorilla/mux, iris, and net/http.

Rebuilt core — no more external OpenAPI dependency

The generator, reflector, and validator have been fully rebuilt from scratch. The biggest consequence: spec no longer depends on github.com/swaggest/openapi-go. The entire OpenAPI model, schema reflection, and spec serialization is now implemented natively.

This has a few practical effects:

  • The schema definition naming convention has changed — definition names are now prefixed with the caller package name by default. If you have snapshot tests or golden files comparing raw spec output, expect those names to change.
  • Reflection behavior is more consistent across all versions and adapters.
  • The validator is tighter and more version-aware.

If you were using any swaggest/openapi-go types directly through spec's re-exports, those are gone. The equivalent types now live in github.com/oaswrap/spec/openapi.

Automatic path parameter injection

If a route pattern contains a {param} segment but no matching path parameter declaration in the operation, spec now injects a string-typed path parameter automatically. This prevents the validator from flagging undeclared path parameters on routes where you haven't explicitly modeled the input struct.

You can still declare path parameters explicitly — explicit declarations take precedence. This is strictly a fallback for routes where the path variable is consumed by the handler but not reflected in a request struct.

Breaking changes

httprouter adapter removed. If you're using httprouteropenapi, migrate to another adapter or copy the adapter implementation into your own project. The adapter depended on a library that no longer receives maintenance.

Upgrade

go get github.com/oaswrap/spec@v0.5.0

After upgrading, run ValidateReport() on your existing spec to catch any issues the tighter validator surfaces. If you have golden-file tests comparing raw spec output, update them to account for the definition name prefix change.

Issues and feedback welcome on GitHub.