A TypeScript Zod v4-inspired validation library for Go with strict type semantics, fluent schemas, and JSON Schema interoperability
- Strict type semantics: Value and pointer schemas accept exact input types unless you explicitly opt into coercion.
- Dual parsing modes: Use
Parse(any)for dynamic data andStrictParse(T)when the input type is already known. - Rich schema surface: Compose primitives, collections, structs, unions, intersections, metadata, transforms, and refinements.
- Struct tags: Build schemas from Go structs with
gozod:"..."rules and alternate tag names throughWithTagName. - Optional code generation: Use
gozodgenfor generated schema helpers in tag-heavy hot paths. - Localized errors: Inspect
*gozod.ZodError, flatten or prettify failures, and use locale bundles fromlocales/. - JSON Schema bridge: Convert to and from JSON Schema Draft 2020-12 with the bundled
jsonschemapackage. - Curated dependency surface: Built on JSON v2,
jsonschema,deepclone, and i18n helpers instead of a framework stack.
go get github.com/kaptinlin/gozodRequires Go 1.26+.
package main
import (
"fmt"
"log"
"github.com/kaptinlin/gozod"
)
func main() {
schema := gozod.String().Min(2).Email()
value, err := schema.Parse("dev@example.com")
if err != nil {
log.Fatal(err)
}
fmt.Println(value)
}GoZod keeps runtime parsing and compile-time constrained parsing separate.
nameSchema := gozod.String().Min(2).Max(50)
name, err := nameSchema.Parse("Alice")
if err != nil {
log.Fatal(err)
}
strictName, err := nameSchema.StrictParse("Alice")
if err != nil {
log.Fatal(err)
}
fmt.Println(name, strictName)Use Parse(any) when data arrives from JSON, maps, or other dynamic sources. Use StrictParse(T) when your program already has the target Go type and you want the strict side of the API.
Use FromStruct[T]() for declarative validation on native Go structs.
package main
import (
"fmt"
"log"
"github.com/kaptinlin/gozod"
)
type User struct {
Name string `gozod:"required,min=2,max=50"`
Email string `gozod:"required,email"`
Age int `gozod:"min=18,max=120"`
}
func main() {
schema := gozod.FromStruct[User]()
user, err := schema.Parse(User{
Name: "Ada Lovelace",
Email: "ada@example.com",
Age: 36,
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("%+v\n", user)
}If you use a different tag key, pass gozod.WithTagName("validate").
For generated helpers, install and run gozodgen:
go install github.com/kaptinlin/gozod/cmd/gozodgen@latest
go generate ./...See docs/tags.md and cmd/gozodgen for the full struct-tag and code-generation workflow.
Use Object, Struct, Union, Intersection, and related constructors when you want the schema shape in code.
userSchema := gozod.Object(gozod.ObjectSchema{
"name": gozod.String().Min(2),
"email": gozod.Email(),
"age": gozod.Int().Min(18),
})
contactSchema := gozod.Union([]any{
gozod.Email(),
gozod.URL(),
})
_, _ = userSchema.Parse(map[string]any{
"name": "Grace",
"email": "grace@example.com",
"age": 28,
})
_, _ = contactSchema.Parse("https://example.com")For coercion-first flows, use the constructors in coerce/.
GoZod can translate schemas to JSON Schema Draft 2020-12 and back.
schema := gozod.Object(gozod.ObjectSchema{
"name": gozod.String().Min(1),
"age": gozod.Int().Min(0),
})
jsonSchema, err := gozod.ToJSONSchema(schema)
if err != nil {
log.Fatal(err)
}
result := jsonSchema.ValidateMap(map[string]any{
"name": "Lin",
"age": 30,
})
fmt.Println(result.IsValid())See docs/json-schema.md for conversion details and compatibility notes.
Validation failures return error. Inspect them as *gozod.ZodError when you need structured details.
schema := gozod.String().Min(5)
_, err := schema.Parse("hi")
if err == nil {
return
}
var zodErr *gozod.ZodError
if gozod.IsZodError(err, &zodErr) {
fmt.Println(gozod.PrettifyError(zodErr))
}See docs/error-customization.md and docs/error-formatting.md for custom messages and output shapes.
- docs/api.md — API reference and method surface
- docs/basics.md — core concepts and common patterns
- docs/tags.md — struct-tag validation guide
- docs/json-schema.md — JSON Schema conversion
- docs/feature-mapping.md — TypeScript Zod v4 to GoZod mapping
- docs/metadata.md — schema metadata and registries
- examples/README.md — runnable examples by topic
Run an example directly:
go run ./examples/quickstart
go run ./examples/struct_tagsGoZod includes benchmarks for parsing, checks, tags, transforms, and configuration helpers.
- Prefer
StrictParsewhen the input type is already known. - Use coerce/ only when conversion is part of the requirement.
- Use
gozodgenfor tag-heavy hot paths where reflection cost matters.
Run the benchmark suite with:
go test -bench=. ./...task test # Run the default test suite
task test:race # Run race-enabled tests for lightweight packages
task lint # Run golangci-lint and tidy checks
task verify # Run deps, fmt, vet, lint, test, and govulncheck
go test -tags=contractcheck ./types # Audit compile-time schema contractsFor development guidelines and repository conventions, see AGENTS.md.
Contributions are welcome. Run the test and lint commands before opening a pull request, and keep docs and examples aligned with the current API surface.
This project is licensed under the MIT License - see the LICENSE file for details.