Parsing
What is schema.Parse()?
To validate and parse your data into a destination pointer you can use the schema.Parse()
function. The function signature looks like this:
schema.Parse(data, &dest, options...)
This works with any Zog Schema:
// string
var dest string
z.String().Min(3).Parse("test", &dest)
// structs
var dest User
z.Struct(z.Schema{"name": z.String().Min(3)}).Parse(map[string]any{"name": "test"}, &dest)
Under the hood Zog follows the Parsing Execution Structure and does a bunch of things under the hood to make sure your data is parsed correctly. Such as checking for zero values, coercing types, etc...
Parsing Struct Tags
By default zog will use the schema field name as the key for the parsed value. For example:
type User struct {
Name string `zog:"name"`
}
z.Struct(z.Schema{"name": z.String()}).Parse(map[string]any{"name": "test"}, &User{}) // note zog will fetch the value as map[name]
type User struct {
Name string `zog:"name"`
}
z.Struct(z.Schema{"Name": z.String()}).Parse(map[string]any{"name": "test"}, &User{}) // note zog will fetch the value as map[Name]
However, this is not always practical. For example, you may have data coming in in kebab case and you want to parse it into camel case. For this Zog supports a few struct tags:
json
tag which works for JSON input dataform
tag which works for form input dataquery
tag which works for query string input dataenv
tag which works for environment variables see zenv for more infozog
a catch all tag which works for any input data
The priority of keys is as follows:
json
||form
||query
||env
->zog
-> schema field name
You can mix and match without issue:
type User struct {
Name string `zog:"first-name"`
LastName string `query:"last_name" json:"last-name"`
}
z.Struct(z.Schema{"name": z.String(), "lastName": z.String()}).Parse(map[string]any{"first-name": "test", "lastName": "Doe"}, &User{})
Coercion
Zog will attempt to coerce the data into the correct type. For example if you have a z.Int()
schema and you pass in a "1"
it will be coerced into an int
type. This behaviour, like almost everything else in Zog, can be customized. Zog provides two main ways to customize coercion:
- Global Coercion - Change the default coercion behaviour for all schemas. More details on this in the configuration page.
- Per schema coercers - Define custom coercion functions for your schemas.
Per schema coercers
You can define custom coercion functions for your schemas by using the z.WithCoercer()
schema option.
z.String(z.WithCoercer(func(data any) (any, error) {
return "test", nil // now the result will be "test" no matter the input
})).Parse("abc", &dest) // dest will be "test"
Parsing Execution Structure
Parsing execution structure is quite simple. It just does roughly this:
- Check for nil value
- If nil take into account if schema has default value or is required
- Coerce value to the correct type otherwise
- Run validation loop
- If a test fails, an issue is added
- If you return an error from a transform, the execution stops and that error is returned.
- If catch is active any error triggers it and stops the execution.