Socket
Socket
Sign inDemoInstall

zgo.at/zvalidate

Package Overview
Dependencies
1
Alerts
File Explorer

Install Socket

Detect and block malicious and high-risk dependencies

Install

    zgo.at/zvalidate

This contains a copy of utf.ValidString() which also considers NULL bytes invalid. Package zvalidate provides simple validation for Go. See the README.markdown for an introduction.


Version published

Readme

Source

Build Status codecov GoDoc

Simple validation for Go. Some things that make it different from the (many) other libraries:

  • No struct tags – which I don't find a good tool for this – just functions.
  • Validations return parsed values.
  • Easy to display validation errors in UI.
  • Doesn't use reflection (other than type assertions); mostly typed.
  • No external dependencies.
  • Easy to add nested validations.
  • Not tied to HTTP (useful for validating CLI flags, for example).

I originally wrote this at my previous employer (github.com/teamwork/validate), this is an improved (and incompatible) version.

Basic example:

email := "martin@arp42.net"

v := zvalidate.New()
v.Required("email", email)
m := v.Email("email", email)

if v.HasErrors() {
    fmt.Printf("Had the following validation errors:\n%s", v)
}

fmt.Printf("parsed email: %s\n", m.Address)

All validators are just method calls on the Validator struct, and follow the same patterns:

  • The input's zero type (empty string, 0, nil, etc.) is valid. Use the Required() validator if you want to make a parameter required).

  • key string, value [..] are the first two arguments, where key is the parameter name (to display in the error or next to a form) and value is what we want validated (type of value depends on validation).

  • Optionally accept a custom message as the last parameter.

The error text only includes a simple human description such as "must be set" or "must be a valid email". When adding new validations, make sure that they can be displayed properly when joined with commas. A text such as "Error: this field must be higher than 42" would look weird:

must be set, Error: this field must be higher than 42

Validations

List of validations with abbreviated function signature (key string, value [..] omitted):

FunctionDescription
Required()Value must not be the type's zero value
Exclude([]string)Value is not in the exclude list
Include([]string)Value is in the include list
Range(min, max int)Minimum and maximum int value.
Len(min, max int) intCharacter length of string
Integer() int64Integer value
Boolean() boolBoolean value
Domain() []stringDomain name; returns list of domain labels.
URL() *url.URLValid URL
Email() mail.AddressEmail address
IPv4() net.IPIPv4 address
IP() net.IPIPv4 or IPv6 address
HexColor() (uint8, uint8, uint8)Colour as hex triplet (#123456 or #123)
Date(layout string)Parse according to the given layout
Phone() stringLooks like a phone number

You can set your own errors with v.Append():

if !some_complex_condition {
    v.Append("foo", "must be a valid foo")
}

Nested validations

Sub() allows adding nested subvalidations; this is useful if a form creates more than one object.

For example:

v := zvalidate.New()
v.Sub("settings", -1, customer.Settings.Validate())

This will merge the Validator object in to v and prefix all the keys with settings., so you'll have settings.timezone (instead of just timezone).

You can also add arrays:

for i, a := range customer.Addresses {
    a.Sub("addresses", i, c.Validate())
}

This will be added as addresses[0].city, addresses[1].city, etc.

If the error is not a Validator then the Error() text will be added as just the key name without subkey (same as v.Append("key", "msg")); this is mostly to support cases like:

func (Customer c) Validate() {
    v := validate.New()

    ok, err := c.isUniqueEmail(c.Email)
    if err != nil {
        return err
    }
    if !ok {
        v.Append("email", "must be unique")
    }

    return v.ErrorOrNil()
}

Displaying errors

The Validator type satisfies the error interface, so you can return them as errors; usually you want to return ErrorOrNil().

The general idea is that validation errors should usually be displayed along the input element, instead of a list in a flash message (but you can do either).

  • To display a flash message or CLI just call String() or HTML().

  • For Go templates there is a TemplateError() helper which can be added to the template.FuncMap. See the godoc for that function for details and an example.

  • For JavaScript Errors is represented as map[string][]string, and marshals well to JSON; in your frontend you just have to find the input belonging to the map key. A simple example might be:

    var display_errors = function(errors) {
        var hidden = '';
        for (var k in errors) {
            if (!errors.hasOwnProperty(k))
                continue;
    
            var elem = document.querySelector('*[name=' + k + ']')
            if (!elem) {
                hidden += k + ': ' + errors[k].join(', ');
                continue;
            }
    
            var err = document.createElement('span');
            err.className = 'err';
            err.innerHTML = 'Error: ' + errors[k].join(', ') + '.';
            elem.insertAdjacentElement('afterend', err);
        }
    
        if (hidden !== '')
            alert(hidden);
    };
    
    display_errors({
        'xxx':    ['oh noes', 'asd'],
        'hidden': ['asd'],
    });
    

caveat: if there is an error with a corresponding form element then that won't be displayed. This is why the above examples Pop() all the errors they want to display, and then display anything that's left. This prevents "hidden" errors.

i18n

There is no direct support for i18n, but the messages are all exported as Message* and can be replaced by your i18n system of choice.

FAQs

Last updated on 16 Mar 2020

Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc