:balloon: A lightweight struct validator for Go

gody

Mentioned in Awesome Go GoDoc Go Report Card Build Status Coverage Status GitHub release (latest by date)

Go versions supported

Installation

go get github.com/guiferpa/gody/v2

Usage

package main

import (
    "encoding/json"
    "fmt"
    "net/http"

    gody "github.com/guiferpa/gody/v2"
    "github.com/guiferpa/gody/v2/rule"
) 

type RequestBody struct {
    Name string `json:"name" validate:"not_empty"`
    Age  int    `json:"age" validate:"min=21"`
}

func HTTPHandler(v *gody.Validator) http.HandlerFunc {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        var body RequestBody
        if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
	    ...
    	}
	defer r.Body.Close()

	if isValidated, err := v.Validate(body); err != nil {
	    ...                                                                                
	}
    })
}

func main() {
    validator := gody.NewValidator()

    validator.AddRules(rule.NotEmpty, rule.Min)

    port := ":3000"
    http.ListenAndServe(port, HTTPHandler(validator))
}

Others ways for validation

There are others ways to valid a struct, take a look on functions below:

  • RawValidate - It's a function that make validate with no rule, it's necessary put the struct for validation, some rule(s) and tag name.
gody.RawValidate(interface{}, string, []gody.Rule) (bool, error)
  • Validate - It's a function that make validate with no rule, it's necessary put the struct for validation and some rule(s).
gody.Validate(interface{}, []gody.Rule) (bool, error)
  • RawDefaultValidate - It's a function that already have built-in rules configured, it's necessary put the struct for validation, tag name and optional custom rule(s).
gody.RawDefaultValidate(interface{}, string, []gody.Rule) (bool, error)
  • DefaultValidate - It's a function that already have built-in rules configured, it's necessary put the struct for validation and optional custom rule(s).
gody.DefaultValidate(interface{}, []gody.Rule) (bool, error)

Contribution policies

  1. At this time the only policy is don't create a Pull Request directly, it's necessary some discussions for some implementation then open an issue before to dicussion anything about the project.
Owner
Guilherme Paixão
🍕 A lover of containers, travel, games and algorithms.
Guilherme Paixão
Comments
  • Loyalty on show field name

    Loyalty on show field name

    Problem

    There is a problem when the JSON API has a field in camelCase. For this scene the gody change the field name to lowercase letters.

    For example:

    Request

    POST - /users

    Body

    {
      "firstName": ""
    }
    

    Output

    field firstname cannot be empty

    Solution

    Probably a solution for it can be get field names from tag json, for example:

    type User struct {
        FirstName string `json:"firstName" validate:"not_empty"`
    }
    

    In this case the field name must will be firstName

  • Adjustments for better maintainability

    Adjustments for better maintainability

    Unexported functions which were not needed by outside user, added some documentation, made tag name optional and made "validate" the default tag name when none is passed. Validate now accepts many tag names, and uses any of the tag names to serialize when found.

  • required-validation

    required-validation

    In release v1 the required-validation is only applicable for strings type. However there are scenes that someone needs of required-validation for default values in Golang that was not necessary inputted.

    Code example:

    type UserRequestBody struct {
        FirstName string `json:"fname"`
        LastName  string `json:"lname"`
        Age       int    `json:"age" validate:"required=true"`
    }
    
    var b UserRequestBody
    payload := `{"fname": "Arthur", "lname": "Coimbra"}`
    
    requestBody := strings.NewReader(payload)
    if err := json.NewDecoder(requestBody).Decode(&b); err != nil {
        ...
    }
    
    fmt.Println(b.Age) // 0
    

    This code above must is wrong because of the inputted payload not contains an age value and given validate tag this validation must return an error about it. Because of Golang default values the instance of struct contains a value 0 but it's not correct if the tag validate:"required=true" is used.

    Ps.: The required rule name will be replaced by not_empty coming more sense for itself. Take a look at #7 .

  • Multi level validate

    Multi level validate

    This package already make validation about the first layer of a struct but when we get on second layer it's not work.

    Take a look at test commented about this feature: https://github.com/guiferpa/gody/blob/master/validate_test.go#L72

  • Remove the necessity for tag in struct and slice validation

    Remove the necessity for tag in struct and slice validation

    It's a problem how gody works today because of necessity for tags in slice and struct.

    An example about how it works today:

    type Owner struct {
        Name string `validate:"not_empty"`
    }
    
    type Task struct {
        Title       string `validate:"not_empty"`
        Description string `validate:"max_bound=140"`
    }
    
    type TaskList struct {
        Owner Owner  `validate:"required"` // It's necessary
        Tasks []Task `validate:"required"` // It's necessary
    }
    

    The tag with some value is necessary for validation of fields above (Owner and Tasks).

    Take a look at line: https://github.com/guiferpa/gody/blob/master/serialize.go#L49-L53

    There is the condition to serialize a field. However today it's just verified if it has a tag with any value or haven't, if it contains tag with some value it'll be serialize but if not it'll be ignored.

    The purpose is to make the validation even if there's tag or not. Letting the struct typing more clean like this example below:

    ...
    
    type TaskList struct {
        Owner Owner  // Tag isn't necessary anymore
        Tasks []Task // Tag isn't necessary anymore
    }
    
  • Change name of required rule

    Change name of required rule

    Change required rule name by not_empty because of word sense. For now the required rule just take care of string values. Changing to not_empty it'll give more sense for itself.

  • Boolean rule implementation

    Boolean rule implementation

    It's not necessary parameters for some rules in tag for runtime validation.

    Example:

    • There's no sense put true as parameter value below
    type Body struct {
    	Text string `json:"text" validate:"required=true"`
    }
    
    • Instead of the example above it could be just the rule name
    type Body struct {
    	Text string `json:"text" validate:"required"`
    }
    
    
  • gody.Validate contract

    gody.Validate contract

    Until now to validate some struct we need to type as below:

    ...
    
    b := struct {
      Test string `validate:"required=true"`
    }{"issue"}
    
    valid, err := gody.Validate(b, /* the rules implemented will be put here */)
    
    ...
    

    There's just one way to put your custom rules, for this I was thinking something looks like it:

    For default rules

    ...
    
    b := struct {
      Test string `validate:"not_empty"`
    }{"issue"}
    
    valid, err := gody.DefaultValidate(b, /* the rules implemented will be put here */)
    
    ...
    

    Or

    ...
    
    b := struct {
      Test string `validate:"not_empty"`
    }{"issue"}
    
    rules := []gody.Rule{
        rule.NotEmpty,
        /* the rules implemented will be put here together with default rules */
    }
    valid, err := gody.Validate(b, rules)
    
    ...
    

    For custom rules

    ...
    
    validator := gody.NewValidator()
    
    rules := []gody.Rule{
        /* the rules implemented will be put here */
    }
    if err := validator.AddRules(rules); err != nil {
        ...
    }
    
    valid, err := validator.Validate(b)
    
    ...
    
  • Set rule from dynamic values

    Set rule from dynamic values

    Nowadays there's only support to static configuration. For example, configuring some rule to Enum validation it's necessary set this Enum value statically.

    I had on problem using defined const values in my source code in validation rule, follow the code example below:

    ...
    
    type Status string
    
    const (
        StatusCreated Status = "__CREATED__"
        StatusPending Status = "__PENDING__"
        StatusDoing   Status = "__DOING__"
        StatusDone    Status = "__DONE__"
    )
    
    ...
    
    type Task struct {
        Name   string
        Status Status `json:"status" validate:"enum=__CREATED__,__PENDING__,__DOING__,__DONE__"`
    }
    
    ...
    
    validator := gody.NewValidator()
    validator.AddRules(rule.Enum)
    
    task := Task{}
    validator.Validate(task)
    

    With the previous example we have a problem of duplicity and my suggestion for the static config problem is likely this source code below:

    type Status string
    
    const (
        StatusCreated Status = "__CREATED__"
        StatusPending Status = "__PENDING__"
        StatusDoing   Status = "__DOING__"
        StatusDone    Status = "__DONE__"
    )
    
    ...
    
    type Task struct {
        Name   string
        Status Status `json:"status" validate:"enum={status}"`
    }
    
    ...
    
    validator := gody.NewValidator()
    validator.AddRuleParameters(...[]rule.Parameter{
        {
            Name: "status", 
            Value: fmt.Sprintf("%s,%s,%s,%s", StatusCreated, StatusPending, StatusDoing, StatusDone),
        },
    })
    validator.AddRules(rule.Enum)
    
    task := Task{}
    validator.Validate(task)
    
    
A lightweight model validator written in Go.

validator A lightweight model validator written in Go. quickstart package main import ( "fmt" v "github.com/go-the-way/validator" ) func main() {

Sep 27, 2022
:100:Go Struct and Field validation, including Cross Field, Cross Struct, Map, Slice and Array diving

Package validator Package validator implements value validations for structs and individual fields based on tags. It has the following unique features

Jan 1, 2023
jio is a json schema validator similar to joi
jio is a json schema validator similar to joi

jio Make validation simple and efficient ! 中文文档 Why use jio? Parameter validation in Golang is really a cursing problem. Defining tags on structs is n

Dec 25, 2022
A norms and conventions validator for Terraform

This tool will help you ensure that a terraform folder answer to your norms and conventions rules. This can be really useful in several cases : You're

Nov 29, 2022
Golang parameter validation, which can replace go-playground/validator, includes ncluding Cross Field, Map, Slice and Array diving, provides readable,flexible, configurable validation.
Golang parameter validation, which can replace go-playground/validator, includes ncluding Cross Field, Map, Slice and Array diving, provides readable,flexible, configurable validation.

Checker 中文版本 Checker is a parameter validation package, can be use in struct/non-struct validation, including cross field validation in struct, elemen

Dec 16, 2022
golang request validator

validator Golang 参数验证器,目前只支持POST请求,JSON格式参数验证 亮点 1、验证时只要有一个错误,错误信息立即返回 2、可自定义参数别名显示错误信息;详情见_example文件 使用 go mod -u github.com/one-gold-coin/validator

Sep 30, 2021
golang rule-based string validator

gosv golang rule-based string validator usage import "github.com/s0rg/gosv" var MyRules = []gosv.Rule{ gosv.MinLen(8), gosv.MaxLen(64), gosv.MinLo

Nov 20, 2021
Checker/validator for Hong Kong IDs

hkidchecker Checker/validator for Hong Kong IDs Description This Go package validates Hong Kong ID card IDs. Useful for example for validating form in

Oct 13, 2021
The Hyperscale InputFilter library provides a simple inputfilter chaining mechanism by which multiple filters and validator may be applied to a single datum in a user-defined order.

Hyperscale InputFilter Branch Status Coverage master The Hyperscale InputFilter library provides a simple inputfilter chaining mechanism by which mult

Oct 20, 2021
OpenShift OLM Catalog Validator

OpenShift OLM Catalog Validator Overview It is an external validator which can be used with Operator-SDK to check the vendor-like criteria to publish

Nov 22, 2021
Vat ID Validator for Germany

German Vat Validator service This project has been developed using Hexagonal architecture and repository pattern. How to run? docker-compose up -d Cal

Nov 4, 2021
A demo project shows how to use validator to validate parameters

validator-demo This project is a demo project shows how to use validator to validate parameters use case install requirements go get github.com/favadi

Jan 10, 2022
Iran National Id, Bank Card Number, Mobile Number Validator for golang

Iran IDValidator Iran National Id, Bank Card Number, Mobile Number Validator for golang Installation go get -u github.com/mohammadv184/idvalidator Us

Dec 20, 2021
Gin Middleware to extract json tag value from playground validator's errors validation

Json Tag Extractor for Go-Playground Validator This is Gin Middleware that aim to extract json tag and than store it to FieldError.Field() object. Ins

Jan 14, 2022
Validator - Replace the validation framework used by gin

validator Replace the validation framework used by gin replace mod:replace githu

Jan 18, 2022
Struct validation using tags

Govalid Use Govalid to validate structs. Documentation For full documentation see pkg.go.dev. Example package main import ( "fmt" "log" "strings"

Dec 6, 2022
An idiomatic Go (golang) validation package. Supports configurable and extensible validation rules (validators) using normal language constructs instead of error-prone struct tags.

ozzo-validation Description ozzo-validation is a Go package that provides configurable and extensible data validation capabilities. It has the followi

Jan 7, 2023
Dec 28, 2022
An interesting go struct tag expression syntax for field validation, etc.

go-tagexpr An interesting go struct tag expression syntax for field validation, etc. Usage Validator: A powerful validator that supports struct tag ex

Jan 9, 2023