https://github.com/alexhcjp/purify
Purify is a Go library for struct validation based on tags. It allows you to easily validate data within structs using purify tags, making your code cleaner and easier to maintain.
https://github.com/alexhcjp/purify
form go golang validator
Last synced: 5 months ago
JSON representation
Purify is a Go library for struct validation based on tags. It allows you to easily validate data within structs using purify tags, making your code cleaner and easier to maintain.
- Host: GitHub
- URL: https://github.com/alexhcjp/purify
- Owner: AlexHCJP
- License: bsd-3-clause
- Created: 2024-09-30T21:13:07.000Z (almost 2 years ago)
- Default Branch: main
- Last Pushed: 2024-10-01T00:08:54.000Z (almost 2 years ago)
- Last Synced: 2025-08-21T19:39:39.703Z (11 months ago)
- Topics: form, go, golang, validator
- Language: Go
- Homepage: https://pkg.go.dev/github.com/contributors-company/purify
- Size: 9.77 KB
- Stars: 3
- Watchers: 0
- Forks: 0
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Purify
**Purify** is a Go library for struct validation based on tags. It allows you to easily validate data within structs using `purify` tags, making your code cleaner and easier to maintain.
## Table of Contents
- [Getting Started](#getting-started)
- [Installation](#installation)
- [Requirements](#requirements)
- [Usage](#usage)
- [Example](#example)
- [Available Validation Tags](#available-validation-tags)
- [Custom Validators](#custom-validators)
- [Creating a Custom Validator](#creating-a-custom-validator)
- [Password Validation Example](#password-validation-example)
- [Error Handling](#error-handling)
- [Testing](#testing)
- [Contributing](#contributing)
- [License](#license)
- [Author](#author)
- [Acknowledgments](#acknowledgments)
## Getting Started
### Installation
Install the library using `go get`:
```bash
go get github.com/contributors-company/purify
```
Import the package into your project:
```go
import "github.com/contributors-company/purify"
```
### Requirements
- Go 1.13 or higher
## Usage
Purify allows you to validate struct fields using `purify` tags in your struct definitions.
### Example
```go
package main
import (
"fmt"
"github.com/contributors-company/purify"
)
type User struct {
Email string `json:"email" purify:"required|email"`
Username string `json:"username" purify:"required|min(3)|max(20)"`
Age int `json:"age" purify:"min(18)|max(99)"`
}
func main() {
user := User{
Email: "example@example.com",
Username: "example_user",
Age: 25,
}
// Validate the struct
err := purify.ValidateStruct(user)
if err != nil {
fmt.Println("Validation error:", err)
} else {
fmt.Println("Validation successful")
}
}
```
In this example:
- The `Email` field must be filled and contain a valid email address.
- The `Username` field must be filled, have a length of at least 3 and at most 20 characters.
- The `Age` field must be at least 18 and at most 99.
### Available Validation Tags
- `required` — checks that the field is not empty.
- `email` — checks that the field contains a valid email address.
- `min(n)` — checks that the field's value is not less than `n`. For strings, this is the length of the string; for numbers, the value itself.
- `max(n)` — checks that the field's value is not greater than `n`. For strings, this is the length of the string; for numbers, the value itself.
**Example of tag usage:**
```go
type Product struct {
Name string `json:"name" purify:"required|min(3)|max(50)"`
Price float64 `json:"price" purify:"required|min(0.01)"`
}
```
## Custom Validators
Purify provides the ability to create your own validators to extend the library's functionality to meet your project's specific requirements.
### Creating a Custom Validator
To create a custom validator, define a function that matches the `ValidatorFunc` type and register it using `RegisterValidator`.
**`ValidatorFunc` type:**
```go
type ValidatorFunc func(fieldValue string, param string) string
```
- `fieldValue` — the value of the field to be validated.
- `param` — the parameter passed in the validation tag (if any).
- The function should return an error message string or an empty string if the validation passes.
**Example of custom validators:**
```go
func Min() ValidatorFunc {
return func(fieldValue string, param string) string {
minLength, _ := strconv.Atoi(param)
if len(fieldValue) < minLength {
return fmt.Sprintf("minimum length is %s characters", param)
}
return ""
}
}
func Max() ValidatorFunc {
return func(fieldValue string, param string) string {
maxLength, _ := strconv.Atoi(param)
if len(fieldValue) > maxLength {
return fmt.Sprintf("maximum length is %s characters", param)
}
return ""
}
}
func Required() ValidatorFunc {
return func(fieldValue string, _ string) string {
if fieldValue == "" {
return "required field"
}
return ""
}
}
func Email() ValidatorFunc {
return func(fieldValue string, _ string) string {
emailRegex := `^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$`
matched, _ := regexp.MatchString(emailRegex, fieldValue)
if !matched {
return "invalid email"
}
return ""
}
}
// Register the validators
func init() {
RegisterValidator("min", Min())
RegisterValidator("max", Max())
RegisterValidator("required", Required())
RegisterValidator("email", Email())
}
```
### Password Validation Example
Suppose you want to add password validation to meet certain requirements, such as:
- Minimum length of 8 characters.
- At least one digit.
- At least one uppercase letter.
**Creating a custom validator for password:**
```go
func Password() ValidatorFunc {
return func(fieldValue string, _ string) string {
if len(fieldValue) < 8 {
return "password must be at least 8 characters long"
}
if !regexp.MustCompile(`[0-9]`).MatchString(fieldValue) {
return "password must contain at least one digit"
}
if !regexp.MustCompile(`[A-Z]`).MatchString(fieldValue) {
return "password must contain at least one uppercase letter"
}
return ""
}
}
// Register the validator
func init() {
RegisterValidator("password", Password())
}
```
**Using the custom validator in a struct:**
```go
type Credentials struct {
Password string `json:"password" purify:"required|password"`
}
```
**Usage example:**
```go
package main
import (
"fmt"
"github.com/contributors-company/purify"
)
type Credentials struct {
Password string `json:"password" purify:"required|password"`
}
func main() {
creds := Credentials{
Password: "Passw1", // Invalid password
}
// Validate the struct
err := purify.ValidateStruct(creds)
if err != nil {
validationErrors := err.(purify.ValidationError)
for field, errors := range validationErrors.Errors {
fmt.Printf("Field '%s' has the following errors:\n", field)
for _, errMsg := range errors {
fmt.Printf("- %s\n", errMsg)
}
}
} else {
fmt.Println("Validation successful")
}
}
```
**Expected output:**
```
Field 'Password' has the following errors:
- password must be at least 8 characters long
- password must contain at least one uppercase letter
```
## Error Handling
The `ValidateStruct` function returns `nil` if there are no validation errors or an error object with the following structure:
```json
{
"errors": {
"field_name": ["error_message1", "error_message2"],
"another_field": ["error_message"]
},
"message": "General error message"
}
```
**Example of error handling:**
```go
err := purify.ValidateStruct(user)
if err != nil {
validationErrors := err.(purify.ValidationError)
for field, errors := range validationErrors.Errors {
fmt.Printf("Field '%s' has the following errors:\n", field)
for _, errMsg := range errors {
fmt.Printf("- %s\n", errMsg)
}
}
} else {
fmt.Println("Validation successful")
}
```
## Testing
You can run tests using the command:
```bash
go test
```
Sample test from the library:
```go
package purify
import (
"testing"
)
type TestStruct struct {
Name string `json:"name" purify:"required|min(3)|max(20)"`
Email string `json:"email" purify:"required|email"`
Password string `json:"password" purify:"required|password"`
}
func TestValidator(t *testing.T) {
s := TestStruct{
Name: "Al",
Email: "invalid_email",
Password: "pass",
}
// Validate the struct
err := ValidateStruct(s)
if err == nil {
t.Errorf("Expected validation error, got nil")
} else {
validationErrors := err.(ValidationError)
if len(validationErrors.Errors) != 3 {
t.Errorf("Expected 3 validation errors, got %d", len(validationErrors.Errors))
}
}
}
```
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.