Zod inspired schema validation in Go.
- Table of contents
- Introduction
- Installation
- Basic usage
- Primitives
- Literals
- Strings
- Ints
- Float64
- Booleans
- Objects
- Arrays
- Schema methods
validator-go is a simple and extensible validation library for Go. It's heavily inspired by Zod and shares a lot of the same interfaces. This library provides a set of validation schemas for different data types, such as integers, strings, and booleans, and allows you to refine these schemas with custom validation rules.
Ensure you have Go installed (download). Version 1.21
or higher is required.
go get -u github.com/Jamess-Lucass/validator-go
Creating a string schema
import (
schema "github.com/Jamess-Lucass/validator-go"
)
// Creating a schema for strings
mySchema := schema.String();
// Parsing
mySchema.Parse("john"); // => *schema.ValidationResult
mySchema.Parse("john").IsValid(); // => true
mySchema.Parse(12).Errors; // => []
mySchema.Parse(12).IsValid(); // => false
mySchema.Parse(12).Errors; // => [{ "path": "", "message": "Expected string, received int" }]
Creating an object schema
import (
schema "github.com/Jamess-Lucass/validator-go"
)
// Creating a schema for an object
mySchema := schema.Object(map[string]schema.ISchema{
"Username": schema.String().Min(5),
})
// Parsing
type User struct {
Username string
}
user1 := User{
Username: "john_doe",
}
mySchema.Parse(user1).IsValid(); // => true
mySchema.Parse(user1).Errors; // => []
user2 := User{
Username: "john",
}
mySchema.Parse(user2).IsValid(); // => false
mySchema.Parse(user2).Errors; // => [{ "path": "Firstname","message": "String must contain at least 5 character(s)" }]
schema.String()
schema.Int()
schema.Bool()
john := schema.Literal("john");
four := schema.Literal(4);
trueSchema := schema.Literal(true);
schema.String().Max(2)
schema.String().Min(2)
schema.String().Length(2)
schema.String().Url()
schema.String().Includes(string)
schema.String().StartsWith(string)
schema.String().EndsWith(string)
schema.Int().Lt(2)
schema.Int().Lte(2)
schema.Int().Gt(2)
schema.Int().Gte(2)
schema.Int().Positive() // > 0
schema.Int().Nonnegative() // >= 0
schema.Int().Negative() // < 0
schema.Int().Nonpositive() // <= 0
schema.Int().MultipleOf(2)
The same methods are available on Float64
as ints
schema.Bool()
mySchema := schema.Object(map[string]schema.ISchema{
"Username": schema.String().Min(5),
"Firstname": schema.String().Min(2).Max(128),
"Age": schema.Int().Gte(18),
"IsVerified": schema.Bool(),
})
The array schema accepts any type that implements the ISchema
interface, this allows you to parse in other schema.
mySchema := schema.Array(schema.String().Min(2)).Max(4)
The above schema defines an array of strings, each of which has a minimum length of 2, with the overall array max length of 4.
You may utilize array and object to construct a more advanced schema
mySchema := schema.Object(map[string]schema.ISchema{
"Username": schema.String().Min(5),
"Firstname": schema.String().Min(2).Max(128),
"Age": schema.Int().Gte(18),
"Addresses": schema.Array(schema.Object(map[string]schema.ISchema{
"Postcode": schema.String().Min(4).Max(10),
"Country": schema.String().Length(2),
})),
})
All schemas contain certain methods.
Given any schema, you may call the .Parse
method and pass through any data to check it's validity against the schema.
mySchema := schema.String()
mySchema.Parse("john"); // => *schema.ValidationResult
mySchema.Parse("john").IsValid(); // => true
mySchema.Parse(2).Errors; // => []
mySchema.Parse(2).IsValid(); // => false
mySchema.Parse(2).Errors; // => [{ "path": "", "message": "Expected string, received int" }]
You may provide custom validation logic with the .Refine
method. This method must return true
or false
to represent whether validation should be considered successful or unsuccessful.
mySchema := schema.String().Refine(func(value string) bool {
return value == "custom_value"
})
This is helpful if you need to perform some business-level validation. For example, checking a database for some value or making a HTTP request to assert something.
verifiedUserSchema := schema.String().Refine(func(value string) bool {
// Fetch user from data.
// ensure `is_verified` field is true.
return true
})
This may also be used in conjunction with .Object
type User struct {
Firstname string
Lastname string
Age int
}
user := User{
Firstname: "john",
Lastname: "doe",
Age: 10,
}
mySchema := schema.Object(map[string]schema.ISchema{
"Firstname": schema.String().Refine(func(value string) bool {
return value == "john" || value == "jane"
}),
"Lastname": schema.String().Refine(func(value string) bool {
return strings.Contains(value, "doe")
}),
"Age": schema.Int().Lt(10),
}).Refine(func(value map[string]interface{}) bool {
if value["Firstname"] == "jane" {
if age, ok := value["Age"].(int); ok {
return age < 5
}
}
return true
})