<a href="https://github.com/Oudwins/zog">
<img src="https://raw.githubusercontent.com/Oudwins/zog/master/assets/zog-banner.png" alt="Zog, a Zod-like schema parser & validator" />
</a>
Zog is a schema builder for runtime value parsing and validation. Define a schema, transform a value to match, assert the shape of an existing value, or both. Zog schemas are extremely expressive and allow modeling complex, interdependent validations, or value transformations.
Killer Features:
API Stability:
- I will consider the API stable when we reach v1.0.0
- However, I believe very little API changes will happen from the current implementation. The APIs most likely to change are the data providers (please don't make your own if possible use the helpers whose APIs will not change meaningfully) and the z.Ctx most other APIs should remain the same. I could be wrong but I don't expect many breaking changes.
- Although we want to keep breaking changes to a minimum, Zog is still in version 0 and will have breaking changes in the minor versions as per semver. So please be careful when upgrading minor versions.
Or don't, below is the quickstart guide
go get github.com/Oudwins/zog
import (
z "github.com/Oudwins/zog"
)
type User struct {
Name string
Age int
}
var userSchema = z.Struct(z.Shape{
// its very important that schema keys like "name" match the struct field name NOT the input data
"name": z.String().Min(3, z.Message("Override default message")).Max(10),
"age": z.Int().GT(18),
})
Using schema.Parse()
func main() {
u := User{}
m := map[string]string{
"name": "Zog",
"age": "", // won't return an error because fields are optional by default
}
errs := userSchema.Parse(m, &u)
if errs != nil {
// handle errors -> see Errors section
}
u.Name // "Zog"
// note that this might look weird but we didn't say age was required so Zog just skipped the empty string and we are left with the uninitialized int
// If we need 0 to be a valid value for age we can use a pointer to an int which will be nil if the value was not present in the input data
u.Age // 0
}
Using schema.Validate()
func main() {
u := User{
Name: "Zog",
Age: 0, // wont return an error because fields are optional by default otherwise it will error
}
errs := userSchema.Validate(&u)
if errs != nil {
// handle errors -> see Errors section
}
}
The zhttp package has you covered for JSON, Forms and Query Params, just do:
import (
zhttp "github.com/Oudwins/zog/zhttp"
)
err := userSchema.Parse(zhttp.Request(r), &user)
If you are receiving json some other way you can use the zjson package
import (
zjson "github.com/Oudwins/zog/zjson"
)
err := userSchema.Parse(zjson.Decode(bytes.NewReader(jsonBytes)), &user)
The zenv package has you covered, just do:
import (
zenv "github.com/Oudwins/zog/zenv"
)
err := envSchema.Parse(zenv.NewDataProvider(), &envs)
var t = time.Time
// All schemas now return ZogIssueList
errs := Time().Required().Parse("2020-01-01T00:00:00Z", &t)
var dest []string
schema := z.Preprocess(func(data any, ctx z.Ctx) ([]string, error) {
s := data.(string) // don't do this, actually check the type
return strings.Split(s, ","), nil
}, z.Slice(z.String().Trim().Email().Required()))
errs := schema.Parse("foo@bar.com,bar@foo.com", &dest) // dest = [foo@bar.com bar@foo.com]
These are some of the things I want to add to zog before v1.0.0
This project is licensed under the MIT License - see the LICENSE file for details.