Migrating from go-playground/validator
This guide helps you migrate from go-playground/validator to Pedantigo.
Quick Migration (One Line)
For most codebases, migration requires only one line:
func init() {
pedantigo.SetTagName("validate")
}
This tells Pedantigo to read your existing validate:"..." struct tags instead of pedantigo:"...".
Your existing structs work unchanged:
type User struct {
Email string `json:"email" validate:"required,email"`
Age int `json:"age" validate:"min=18,max=120"`
}
// Works with Pedantigo
user, err := pedantigo.Unmarshal[User](jsonData)
Supported Tags (Zero Changes Needed)
These validator tags work identically in Pedantigo:
Core Constraints
required, min, max, len, eq, ne, gt, gte, lt, lte
String Constraints
email, url, uri, uuid, alpha, alphanum, alphaunicode, alphanumunicode, numeric, number, hexadecimal, ascii, printascii, lowercase, uppercase, contains, excludes, startswith, endswith, startsnotwith, endsnotwith, containsany, excludesall, excludesrune
Enum/Choice
oneof, oneofci
Field Comparisons
eqfield, nefield, gtfield, gtefield, ltfield, ltefield, eqcsfield, necsfield, gtcsfield, gtecsfield, ltcsfield, ltecsfield
Conditional Validation
required_if, required_unless, required_with, required_without, required_with_all, required_without_all, excluded_if, excluded_unless, excluded_with, excluded_without, excluded_with_all, excluded_without_all
Network
ip, ipv4, ipv6, cidr, cidrv4, cidrv6, mac, hostname, hostname_rfc1123, fqdn, tcp_addr, udp_addr, hostname_port, http_url
Format Validators
datetime, credit_card, isbn, isbn10, isbn13, issn, ssn, ein, e164, base64, base64url, base64rawurl, json, jwt, html, hexcolor, rgb, rgba, hsl, hsla, latitude, longitude, md4, md5, sha256, sha384, sha512, mongodb, cron, semver, ulid, luhn_checksum, bitcoin_addr, bitcoin_addr_bech32, ethereum_addr
ISO Codes
iso3166_1_alpha2, iso3166_1_alpha3, iso3166_1_alpha_numeric, iso4217, bcp47_language_tag, postcode_iso3166_alpha2
Collections
dive, unique
OR Operator
hexcolor|rgb|rgba (validates if ANY matches)
Aliases
iscolor (expands to hexcolor|rgb|rgba|hsl|hsla)
Tags You Can Remove
These validator tags are not needed in Pedantigo:
| Tag | Why Not Needed |
|---|---|
omitempty | Pedantigo tracks JSON field presence. Empty values skip validation unless required. |
omitnil | Nil pointers are handled automatically. |
omitzero | Zero values skip validation unless required. |
- | Simply don't add a tag. |
structonly | Not needed - Pedantigo validates all fields by default. |
nostructlevel | Not needed. |
isdefault | Not needed - check for zero value in code. |
Example migration:
// validator
Email string `validate:"omitempty,email"`
// pedantigo (same behavior)
Email string `validate:"email"`
Custom Validator Registration
RegisterAlias
// validator
validate.RegisterAlias("is_active", "oneof=active enabled")
// pedantigo (identical)
pedantigo.RegisterAlias("is_active", "oneof=active enabled")
Custom Validators
// validator
validate.RegisterValidation("custom", customFunc)
// pedantigo
pedantigo.RegisterConstraint("custom", func(value string) (constraints.Constraint, bool) {
return &myCustomConstraint{}, true
})
Features NOT Supported
The following validator features are not available in Pedantigo:
| Feature | validator Syntax | Workaround |
|---|---|---|
Var() | v.Var(email, "email") | Use struct with single field |
StructPartial | Validate subset of fields | Not supported |
StructExcept | Exclude fields from validation | Not supported |
RegisterValidationCtx | Context-aware validation | Pass context as struct field |
RegisterTagNameFunc | Custom field name function | Uses JSON tag by default |
skip_unless | Skip unless condition | Implement in struct-level validator |
eq_ignore_case | Case-insensitive equality | Use to_lower,eq=value |
ne_ignore_case | Case-insensitive not-equal | Use to_lower,ne=value |
containsrune | Contains specific rune | Use containsany=X with single char |
https_url | URL with https:// only | Use http_url or url,startswith=https:// |
multibyte | Has multibyte characters | Use regexp |
datauri | Data URI format | Use regexp |
base32 | Base32 encoding | Use regexp |
urn_rfc2141 | URN format | Use regexp |
uuid3/4/5 | Specific UUID version | uuid accepts all versions |
timezone | IANA timezone | Custom validator |
image | File is image | Filesystem check in code |
For a complete feature comparison, see API Parity.
These features might be added in the future. If you need any of these features, please open a GitHub issue with your use case.
What You Gain
Pedantigo provides features not available in validator:
| Feature | Description |
|---|---|
| JSON Schema generation | pedantigo.Schema[User]() |
| Unmarshal + Validate | Single step: pedantigo.Unmarshal[User](json) |
| Streaming validation | Parse partial JSON for LLM output |
| Discriminated unions | Union[TypeA, TypeB, TypeC] |
| ExtraAllow mode | Capture unknown JSON fields |
| Secret types | Secret[string] masks in logs |
| Transformers | strip_whitespace, to_lower, to_upper |
| Default values | default=value |
Step-by-Step Migration
-
Add the tag override:
func init() {
pedantigo.SetTagName("validate")
} -
Replace validation calls:
// Before (validator)
validate := validator.New()
err := validate.Struct(user)
// After (pedantigo)
user, err := pedantigo.Unmarshal[User](jsonData)
// or
err := pedantigo.Validate(&user) -
Remove unnecessary tags:
- Delete
omitempty,omitnil,omitzero - Delete
-tags (just remove the tag entirely)
- Delete
-
Test your structs:
go test ./... -
Optional: Migrate tag name: Once validated, you can gradually rename
validatetopedantigotags if desired.
Troubleshooting
"unknown constraint" error
Check if the constraint is in the unsupported list. Use the suggested workaround or implement a custom validator.
Different validation behavior
Pedantigo may have stricter or different validation for some formats. Test edge cases and adjust if needed.
Missing Var() function
Wrap the value in a struct:
// validator
err := validate.Var(email, "required,email")
// pedantigo
type EmailWrapper struct {
Email string `validate:"required,email"`
}
_, err := pedantigo.Unmarshal[EmailWrapper]([]byte(`{"Email":"` + email + `"}`))