go-playground / validator

:100:Go Struct and Field validation, including Cross Field, Cross Struct, Map, Slice and Array diving
MIT License
16.41k stars 1.31k forks source link

Required etc. are ignored on pointer to struct fields #1095

Open rodcheater opened 1 year ago

rodcheater commented 1 year ago

Package version eg. v9, v10:

v10

Issue, Question or Enhancement:

It seems that tags that would reasonably apply to fields which are pointers to structs (such as required and excluded_without) are ignored. Looking at the code, pointer types are substituted for their underlying type at util.go:25, and because the underlying type is a struct type, the tags are therefore ignored.

Code sample, to showcase or reproduce:

import (
    "testing"

    "github.com/go-playground/validator/v10"
    . "github.com/smartystreets/goconvey/convey"
)

type Struct struct {
    Notes     string
    NotesInfo *NotesInfo `validate:"excluded_without=Notes"`
}

type NotesInfo struct{}

func TestValidateStruct(t *testing.T) {
    Convey("Given a struct", t, func() {
        s := Struct{
            NotesInfo: &NotesInfo{},
        }
        Convey("And it is not valid", func() {
            Convey("When validating", func() {
                err := validator.New().Struct(s)
                Convey("Then there is an error", func() {
                    So(err, ShouldNotBeNil)
                })
            })
        })
    })
}
kszafran commented 1 year ago

That looks related to a problem I'm experiencing. I'd like to have a custom validator on a struct or struct pointer field.

type TestStruct struct {
    Geometry *types.Geometry `json:"geometry" binding:"required,something"`
}

func TestValidator(t *testing.T) {
    v := validator.New()
    require.NoError(t, v.RegisterValidation("something", func(fl validator.FieldLevel) bool {
        fmt.Println("I'm here!")
        return false
    }))

    input := `{
      "geometry": {
        "coordinates": [
          31.857764026082037,
          6.866345106185449
        ],
        "type": "Point"
      }
    }`

    var obj TestStruct
    require.NoError(t, json.Unmarshal([]byte(input), &obj))
    require.Error(t, v.Struct(obj))
}

I can't do it with a struct-level validator, because it doesn't get access to the tag, so I couldn't have e.g. validate:"required,geom=2d point".