Giter Site home page Giter Site logo

guiferpa / gody Goto Github PK

View Code? Open in Web Editor NEW
67.0 67.0 5.0 69 KB

:balloon: A lightweight struct validator for Go

Home Page: https://pkg.go.dev/github.com/guiferpa/gody

License: MIT License

Go 100.00%
go golang struct struct-tags validator validator-struct

gody's People

Contributors

guiferpa avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

gody's Issues

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
}

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"`
}

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)

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 .

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)

...

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.

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

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.