Skip to main content

Reference

Generic Zog Schema Methods​

These are methods that can generally be called on any schema type (Some exceptions might exist).

schema.Test(test)        // create a custom test
schema.TestFunc(fn) // create a custom test from a function
schema.Required() // marks field as required
schema.Optional() // marks field as optional
schema.Default(value) // sets default value for field
schema.DefaultFunc(fn) // sets default value for field using a function
schema.Catch(value) // sets catch value for field
schema.CatchFunc(fn) // sets catch value for field using a function
schema.Transform(func(valPtr *T or any, ctx z.Ctx) (any, error)) // adds a transformation function to the schema. This is useful for things like trimming strings, etc.

// VALIDATION METHODS
schema.Parse(data, destPtr) // parses the data into the destination
schema.Validate(dataPtr) // validates the data structure directly. This is a pointer to a struct, slice, string, int, etc...

Options​

Utility functions used to configure schemas, executions, tests, etc...

Test Options​

These are options that can be passed to any test. For more on this checkout the Anatomy of a Schema page.

z.Message()       // sets the issue message for messages generated by the tests
z.MessageFunc(fn) // sets the issue message for messages generated by the tests. This is a function that takes the data as input and returns a string
z.IssueCode() // sets the issue code for messages generated by the tests
z.IssuePath() // sets the issue path for messages generated by the tests

Schema Options​

These are options that can be passed to schemas when creating them.

z.WithCoercer(fn) // sets the coercer for the schema. Only does anything if using schema.Parse()

Execution Options​

These are options that can be passed to schema.Parse() & schema.Validate(). They configure the execution behaviour of the validation.

z.WithIssueFormatter(fn) // sets the issue formatter for the execution. This is used to format the issues messages during execution.
z.WithCtxValue(key, val) // sets a value in the execution context. This is useful for passing values to tests or post transforms.

Schema Types​

// Primitives. Calling .Parse() on these will return []ZogIssue
z.String()
z.Int()
z.Int32()
z.Int64()
z.Float32()
z.Float64()
z.Bool()
z.Time()

// Custom Primitive Schemas
z.StringLike[T]()
z.IntLike[T]()
z.FloatLike[T]()
z.UintLike[T]()
z.BoolLike[T]()

// Complex Types. Calling .Parse() on these will return ZogIssueList (same as primitives). Each issue has a Path field ([]string) indicating where the issue occurred. Root-level issues have a nil Path.
z.Struct(z.Shape{
"name": z.String(),
})
z.Slice(z.String())
z.Ptr(z.String()) // pointer to string
z.Boxed[B, T](schema, unboxFunc, boxFunc) // boxed type wrapper

Utility Schemas​

z.Preprocess()
// Usage:
z.Preprocess(func(data any, ctx z.ctx) (any, error) {
s := data.(string)
return strings.split(s, ","), nil
}, z.slice(z.string())))

Primitive Types​

String​

// Transforms
z.String().Trim() // trims the value of whitespace

// Tests / Validations
z.String().Test() // custom test
z.String().Min(5) // validates min length
z.String().Max(10) // validates max length
z.String().Len(5) // validates length
z.String().Email() // validates email
z.String().URL() // validates url
z.String().IPv4() // validates IPv4 address
z.String().UUID() // validates uuid v4
z.String().Match(regex) // matches a regex
z.String().Contains(substring) // validates string contains substring
z.String().ContainsUpper() // validates string contains uppercase letter
z.String().ContainsDigit() // validates string contains digit
z.String().ContainsSpecial() // validates string contains special character
z.String().HasPrefix(prefix) // validates string has prefix
z.String().HasSuffix(suffix) // validates string has suffix
z.String().OneOf([]string{"a", "b", "c"}) // validates string is one of the values. Similar to zod enums

// Utilities
z.String().Not() // Negates the next test/validation

Numbers / Ints & Floats​

// Supported out of the box (see custom schemas for comparable types):
z.Int()
z.Int32()
z.Int64()
z.Float32()
z.Float64()


// Tests / Validators
z.Int().GT(n) // validates int is greater than n
z.Float().GTE(n) // validates float is greater than or equal to n
z.Int().LT(n) // validates int is less than n
z.Float().LTE(n) // validates float is less than or equal to n
z.Int().EQ(n) // validates int is equal to n
z.Float().OneOf([]float64{1.0, 2.0, 3.0}) // validates float is one of the values. Similar to zod enums

// Utilities
z.Int().Not() // Negates the next test/validation
z.Float().Not() // Negates the next test/validation

Booleans​

// Tests / Validators
z.Bool().True() // validates bool is true
z.Bool().False() // validates bool is false
z.Bool().EQ(true) // validates bool is equal to true

Times & Dates​

Use Time to validate time.Time instances

// Tests / Validators
z.Time().After(time.Now()) // validates time is after now
z.Time().Before(time.Now()) // validates time is before now
z.Time().Is(time.Now()) // validates time is equal to now

// Schema Options
z.Time(z.Time.Format(time.RFC3339)) // If input is a string, it will be parsed as a time.Time using the provided layout. time.RFC3339 is the default. Keep in mind this coercion only works when using Parse()

Complex Types​

Structs​

Note structs cannot be required or optional. They just pass through to the underlying ZogSchemas for their fields. If you need to express that a struct might exist and if it does it must be valid, you can use a pointer. i.e z.Ptr(z.Struct(z.Shape{...}))

// usage
s := z.Struct(z.Shape{
"name": String().Required(),
"age": Int().Required(),
})

// UTILITIES
schema.Pick("key1", map[string]bool{"a": true, "b": false}) // creates a new shallow copy of the schema with only the specified fields. It supports both string keys and map[string]bool
schema.Omit("key1", map[string]bool{"a": true, "b": false}) // creates a new shallow copy of the schema omitting the specified fields. It supports both string keys and map[string]bool

schema.Extend(z.Shape{"a": z.String()}) // creates a new shallow copy of the schema with the additional fields
schema.Merge(otherSchema, otherSchema2) // merges two or more schemas into a new schema. Last schema takes precedence for conflicting keys
// Tests / Validators
// None right now

Slices​

// usage
schema := z.Slice(String())

// Tests / Validators
z.Slice(Int()).Min(5) // validates slice has at least 5 elements
z.Slice(Float()).Max(5) // validates slice has at most 5 elements
z.Slice(Bool()).Length(5) // validates slice has exactly 5 elements
z.Slice(String()).Contains("foo") // validates slice contains the element "foo"

// Utilities
z.Slice(String()).Not() // Negates the next test/validation

Pointers​

z.Ptr(z.String())          // validates pointer to string
z.Ptr(z.Slice(z.String())) // validates pointer to slice of strings

// Tests / Validators
z.Ptr(z.String()).NotNil() // Validates pointer is not nil. This is equivalent to Required() for other types

Boxed Types​

Boxed schemas allow you to wrap any Zog schema with custom box/unbox logic. This is useful for working with types that wrap primitive values (like sql.NullString) or implementing custom value extraction patterns (like the driver.Valuer interface).

// Function signatures
type UnboxFunc[B any, T any] func(data B, ctx Ctx) (T, error)
type CreateBoxFunc[T any, B any] func(data T, ctx Ctx) (B, error)

z.Boxed[B, T](schema ZogSchema, unboxFunc UnboxFunc[B, T], boxFunc CreateBoxFunc[T, B]) *BoxedSchema[B, T]

Parameters:

  • B: The boxed type (the wrapper type)
  • T: The inner type (the type that the schema validates)
  • schema: The Zog schema to validate the inner type
  • unboxFunc: Function to extract the inner value from the box
  • boxFunc: Function to create a new box from the validated inner value

Usage Examples:

//
//
// Example 1: driver.Valuer pattern
//
//

type StringValuer interface {
Value() (string, error)
}

schema := z.Boxed(
z.String().Min(3),
func(b StringValuer, ctx z.Ctx) (string, error) { return b.Value() },
func(s string, ctx z.Ctx) (StringValuer, error) { return myStringValuer{v: s}, nil }, // you can pass nil here if you don't need to box values.
)

var valuer StringValuer
schema.Parse("hello", &valuer) // valuer.Value() will be "hello"
valuer = createValuer("hello2")
schema.Validate(&valuer) // valuer.Value() will be "hello2"


// Example 2: Nullable pattern (like sql.NullString)
type NullString struct {
String string
Valid bool
}

schema := z.Boxed(
z.String().Min(3),
func(ns NullString, ctx z.Ctx) (string, error) {
if !ns.Valid {
return "", errors.New("null string is not valid")
}
return ns.String, nil
},
func(s string, ctx z.Ctx) (NullString, error) {
return NullString{String: s, Valid: true}, nil
},
)

// Example 3: Omittable pattern

type Omittable[T any] interface {
Value() T
IsSet() bool
}

schema := z.Boxed(
z.Ptr(z.String().Min(3)),
func(o Omittable[string], ctx z.Ctx) (*string, error) {
if o.IsSet() {
val := o.Value()
return &val, nil
}
return nil, nil
},
func(s *string, ctx z.Ctx) (Omittable[string], error) {
return createOmittable(s), nil
},
)

Parse vs Validate:

  • Parse: Accepts raw data, box values (B), or pointers to boxes (*B). If the input is a box, it unboxes it first before processing. The value will be boxed back into the original type if a boxFunc is provided.
  • Validate: Validates an existing box value, applies transformations, and re-boxes the result back into the original box if a boxFunc is provided.

Notes:

  • Transforms, defaults, catch values, and all other schema features work normally and propagate back to the box
  • Boxed schemas can be nested inside Struct schemas
  • The boxFunc is called after validation/transformation to create the final boxed value