'How can go-validator check fields against their zero value?

I'm trying to use https://github.com/go-playground/validator and need to ensure that user configuration has an inner struct populated (i.e. not Zero) while still allowing optional configuration:

type Config struct {
    Required Setting `validate:"required"`
    Optional Setting
}

type Setting struct {
    Val string
}

See https://play.golang.org/p/P_6qY7H64sO on playground.

In other words: can I make a field containing a nested struct required in terms of validation rules triggered against the nested struct while having a different field with the same nested struct type optional?

The optional field struct should still be validated if any of its fields are non-zero (i.e. the optional field is populated and hence needs validation).

Update I‘ve noticed the structonly tag but the docs are sketchy and I can‘t get it to work as described above.



Solution 1:[1]

Case 1 If you want to skip optional struct

I think you need this

package main

import (
    "fmt"

    "github.com/go-playground/validator"
)

// Config : Config Struct
type Config struct {
    Required Setting
    Optional Setting `validate:"-"`
}

// Setting : Setting Struct
type Setting struct {
    Val string `validate:"required"`
}

func main() {
    val1 := Config{
        Required: Setting{Val: "Hello"},
    }
    val2 := Config{
        Optional: Setting{Val: "Hello"},
    }

    validate := validator.New()
    err := validate.Struct(val1)
    fmt.Println(err)

    err = validate.Struct(val2)
    fmt.Println(err)
}

Note the validate:"-" will skip validation for that field

Go Playground

====================================================================

Case 2 If you want to optional validation in different cases

Or if you want different validation in different conditions using same struct

you can do a second validator with different tag like so

package main

import (
    "fmt"

    "github.com/go-playground/validator"
)

// Config : Config Struct
type Config struct {
    Required Setting
    Optional Setting
}

// Setting : Setting Struct
type Setting struct {
    Val string `validate:"required" valid:"omitempty,len=5"`  //<---- See This
}

func main() {
    val1 := Config{
        Required: Setting{Val: "Hello"},
    }
    val2 := Config{
        Optional: Setting{Val: "Hello"},
    }

    validate := validator.New()
    err := validate.Struct(val1)
    fmt.Println(err)

    err = validate.Struct(val2)
    fmt.Println(err)

    fmt.Println("Second Validator")
    // New Validator
    validate2 := validator.New()

    validate2.SetTagName("valid") //<---- See This
    err = validate2.Struct(val1)
    fmt.Println(err)

    val1.Optional.Val = "Hel"
    err = validate2.Struct(val1)
    fmt.Println(val1, err)

    val1.Optional.Val = "Hello"
    err = validate2.Struct(val1)
    fmt.Println(val1, err)

}

Go Playground

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1