Simple schema validation toolkit for Golang with Zod-like API.
Add v
to your Golang project:
go get -u github.com/abyanmajid/[email protected]
Start composing schemas, and use them to validate your data:
type Applicant struct {
Name string `json:"name"`
Email string `json:"email"`
LinkedIn string `json:"linkedin"`
University string `json:"university"`
WAM int `json:"wam"`
HasGraduated bool `json:"has_graduated"`
Courseworks []string `json:"courseworks"`
Born time.Time `json:"born"`
}
var unis = []string{"USYD", "UMELB", "UNSW"}
func isValidApplicant(a *Applicant) bool {
// Name must be a string [1, 128] characters long.
name := v.String("Name").Min(1).Max(128).Parse(a.Name)
// Email must be of valid email format
email := v.String("Email").Email().Parse(a.Email)
// URL must be of valid URL format
linkedIn := v.String("LinkedIn").URL().Parse(a.LinkedIn)
// University must only be "USYD", "UMELB", "UNSW"
university := v.Enum("University", unis).Parse(a.University)
// WAM is an integer
// - greater than or equal (GTE) to 0, and
// - less than or equal to (LTE) 100
wam := v.Integer("WAM").Gte(0).Lte(100).Parse(a.WAM)
// Has graduated? Yes (true) or No (false)?
hasGraduated := v.Boolean("HasGraduated").Parse(a.HasGraduated)
// Collection of courseworks taken
courseworks := v.Array("Courseworks", v.String("Coursework").Schema).Parse(a.Courseworks)
// Day and time born following standard ISO format
born := v.Date("Born").Max(time.Now()).Parse(a.Born)
// Assert whether all validation checks has passed
return name.Ok && email.Ok && linkedIn.Ok && university.Ok &&
wam.Ok && hasGraduated.Ok && courseworks.Ok && born.Ok
}
The Result
struct also has other fields apart from Ok
, including:
Errors
(array of validation checks not passed)Value
(post-validation typesafe value, which is useful if your original data is of variable type e.g.,any
/interface{}
)Path
(the name you passed in for the data, e.g.,MyPath123
inv.String("MyPath123")
)
String
- Length validators:
Min(minLength int)
,Max(maxLength int)
,Length(length int)
- Email validator:
Email()
- URL validator:
URL()
- Regex validator:
Regex(regex *regexp.Regexp)
- Substring validators:
Includes(substr string)
,StartsWith(prefix string)
,EndsWith(suffix string)
- Datetime validators:
Date()
,Time()
- IP validators:
IP()
,CIDR()
- ID validators:
UUID()
,NanoID()
,CUID()
,CUID2()
,ULID()
Number (Integer, Float)
- Comparison validators:
Gt(lowerBound T)
,Gte(lowerBound T)
,Lt(upperBound T)
,Lte(upperBund T)
, - Sign validators:
Positive()
,NonNegative()
,Negative()
,NonPositive()
, - Multiplicity validator:
MultipleOf(step T)
- Infinity validator:
Finite()
Where T
is int
for Integer
and float64
for Float
Nil, Any, Never
No chaining validators available.
No chaining validators available.
No chaining validators available.
If you'd given a data of which type that is encoded in another type, you can coerce the data to be encoded in the type you need:
now := v.Coerce.Date("Date").Parse("2025-01-10") // 2025-01-10 00:00:00 +0000 UTC
you_are_funny := v.Coerce.Boolean("You Are Funny").Parse("false") // false
nice := v.Coerce.Integer("Nice").Parse("69") // 69
nice2 := v.Coerce.String("Nice2").Parse(69) // "69"
Array: You can define an array schema using Array(path string, inner *core.Schema[T])
, as shown in the following example:
projects := v.Array("Projects", v.String("Project").Schema)
stockPrices := v.Array("Stock Prices", v.Float("Stock Price").Schema)
Struct: This package currently doesn't provide a way to parse structs.
You can define an enum using Enum(path string, allowedValues []T)
, for any primitive type T
majors := []string{"Computer Science", "Software Development", "Data Science", "Cybersecurity"}
majorsEnum := v.Enum("Majors", majors)
You can define a literal using Literal[T comparable](path string, literalValue T)
for any primitive type T
usPresident2025 := v.Literal("US President 2025", "Donald Trump")
This package is GPL-3.0 licensed.