Documentation
¶
Overview ¶
Package validator composes validation rules over a typed payload.
A Rule is a function; a Validator is an ordered list of them:
v := validator.New(
func(ctx context.Context, o Order) error {
if validator.IsEmpty(o.ID) {
return validator.NewRequiredError("id")
}
return nil
},
func(ctx context.Context, o Order) error {
if o.Total < 0 {
return validator.NewInvalidError("total", o.Total)
}
return nil
},
)
if err := v.Validate(ctx, order); err != nil {
return err
}
Rules run in the order they were given and Validate stops at the first failure, so it reports one problem per call rather than every problem in the payload.
The errors carry a machine-readable ErrorCode alongside their message, which is what lets an HTTP error handler map a validation failure onto a status code without parsing text:
var vErr validator.Error
if errors.As(err, &vErr) && vErr.Code == validator.CodeNotFound {
w.WriteHeader(http.StatusNotFound)
}
Validate wraps the rule error, so reach for errors.As rather than a type assertion.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ContainsKey ¶
func ContainsKey[M ~map[K]V, K comparable, V any](m M, k K) bool
ContainsKey reports whether m holds the key k.
func IsEmpty ¶
func IsEmpty[T comparable](value T) bool
IsEmpty reports whether value equals the zero value of its type. It treats "unset" and "explicitly zero" as the same thing, so a rule built on it cannot tell a missing number from a zero one.
Types ¶
type Error ¶
Error is a validation failure carrying both a human-readable message and the ErrorCode that classifies it. It implements error.
Validate wraps rule errors, so recover this type with errors.As rather than a type assertion.
Example ¶
Validate wraps the rule error, so recovering the code needs errors.As rather than a type assertion.
package main
import (
"context"
"fmt"
"github.com/diegodesousas/go-devkit/pkg/validator"
"github.com/pkg/errors"
)
type order struct {
ID string
Total int
}
func main() {
v := validator.New(func(ctx context.Context, o order) error {
return validator.NewNotFoundError("order")
})
err := v.Validate(context.Background(), order{})
var vErr validator.Error
if errors.As(err, &vErr) {
fmt.Println("code:", vErr.Code)
fmt.Println("message:", vErr.Message)
}
}
Output: code: not_found message: order not found
func NewInvalidError ¶
NewInvalidError reports that value is not acceptable for fieldName.
func NewNotFoundError ¶
NewNotFoundError reports that the named entity does not exist.
func NewRequiredError ¶
NewRequiredError reports that fieldName is mandatory but was not supplied.
type ErrorCode ¶
type ErrorCode string
ErrorCode classifies a validation failure so that callers can branch on the kind of problem without parsing the message.
const ( // CodeRequired means a mandatory attribute was absent or empty. CodeRequired ErrorCode = "required" // CodeInvalid means an attribute was present but its value is not // acceptable. CodeInvalid ErrorCode = "invalid" // CodeNotFound means a referenced entity does not exist. CodeNotFound ErrorCode = "not_found" )
The classes of validation failure this package produces.
type Rule ¶
Rule checks one property of data and returns nil when it holds. Returning one of the errors from NewRequiredError, NewInvalidError or NewNotFoundError gives the failure a machine-readable ErrorCode.
type Validator ¶
Validator runs a fixed list of rules against a value of type T.
Example (StopsAtFirstFailure) ¶
Rules run in order and Validate stops at the first failure, so a payload with two problems reports only the first.
package main
import (
"context"
"fmt"
"github.com/diegodesousas/go-devkit/pkg/validator"
)
type order struct {
ID string
Total int
}
func main() {
v := validator.New(
func(ctx context.Context, o order) error {
return validator.NewRequiredError("id")
},
func(ctx context.Context, o order) error {
return validator.NewInvalidError("total", o.Total)
},
)
fmt.Println(v.Validate(context.Background(), order{Total: -1}))
}
Output: err validator: attribute id is required
func New ¶
New returns a Validator that applies rules in the order given.
Example ¶
package main
import (
"context"
"fmt"
"github.com/diegodesousas/go-devkit/pkg/validator"
)
type order struct {
ID string
Total int
}
func main() {
v := validator.New(
func(ctx context.Context, o order) error {
if validator.IsEmpty(o.ID) {
return validator.NewRequiredError("id")
}
return nil
},
func(ctx context.Context, o order) error {
if o.Total < 0 {
return validator.NewInvalidError("total", o.Total)
}
return nil
},
)
fmt.Println(v.Validate(context.Background(), order{ID: "abc", Total: 10}))
fmt.Println(v.Validate(context.Background(), order{Total: 10}))
}
Output: <nil> err validator: attribute id is required