Validator: Is it possible to perform struct level validation in the same way as field level validation?

Created on 24 Jun 2016  路  9Comments  路  Source: go-playground/validator

So, rather than registering a type of struct that needs to be validated using a particular function, is it possible to put a tag on a struct field (that is itself a struct or ptr to a struct) and call the defined validation method on that struct?

I don't think so from code reading, but just wanted to check incase I'd missed something.

Useful if you have multiple inner structs of the same struct type that need to be validated differently.

e.g.

type Thing struct {
  field1 FooStruct `validate:"checkFooStructIsBlue"`
  field2 FooStruct `validate:"checkFooStructIsOrange"`
}

When validating the above structure would invoke checkFooStructIsBlue passing in FooStruct for field1, and invoke checkFooStructIsOrange passing in FooStruct for field2.

new question

Most helpful comment

Hey @robbrockbank

I agree there are a few things that can be done to make it work, that was never in doubt, however all idea's that I can come up with would make it a little more confusing to use; I could eliminate the confusion and make it easy, but it would require some breaking changes.

So I think that, If you can live with Struct Level Validation for now, I will add this to the list of features for v9 where it can be added in a better manner better.

It will take a while to fully complete v9, but I think it will be worth it for all.

please let me know of any other changes that you may like to see and I'll also try and see what I can do for v9

All 9 comments

@robbrockbank Currently no there is no way to do this, the current design would be to register a validation for the thing Struct and validate field1 and field2 from within.

But you have peaked my interest about possibly adding this type of functionality and so looking to clarify the idea a bit more.

So checkFooStructIsBlue would be a method on the FooStruct like so?


function (f FooStruct) checkFooStructIsBlue(...validation helpers etc) {
//validate here
}

@joeybloggs So I hadn't considered adding methods to the structs themselves rather that it would be akin to user-defined field validation where you register a validator and specify that as the validator for that field - exactly as other fields, but allowing the field to actually be a sub-structure such as field1 or field2in my example above.

The exact use-case I have for this is I some fields across different structures that may contain a string or an int - so i've defined a Int32OrString structure. In each case I want to validate the integer or string values that have been specified (e.g. in one case the field is used to represent protocol - so it take a string of "udp" or "tcp" etc., or can take a numerical value 0-255. I'd like to be able to define the field as:

type Foo struct {
  ...
  field1 Int32OrString "validate:protocol"
  ...

And have a validation function registered with name "protocol" invoked for the value of field1, rather than diving into the structure and validating the separate fields.

I realize I could create separate structures for Protocol adding the Int32OrString as an anonymous field and then adding structure level validation for those types - but really I'd like to conceptually think of the sub-structure as a single field ... certainly the JSON from which it is parsed is a single field.

Thanks for the details @robbrockbank , yes I am definitly interested in adding this sort functionality, I will have to think about what all to pass to the function.

Second part is should the function just return true or false for validation or allow for many fields to be validated like the Struct level validation...any input would be appreciated :)

P.S. It may take me a while as I am creating, updating and maintaining a bunch of other projects in go-playground but promise I will get to it as soon as I can.

Thanks @joeybloggs.

For my use case I'm validating the sub-structure as if it were a single field so the details of which sub-field is at fault is not important. I think that means it can be handled in the same way as a field validator in that it just returns true or false.

Awesome thanks!

Hey @robbrockbank

just letting you know that I started looking into this, I could probably use the existing validation signature and ability to register custom funcs; the only thing I'm having trouble with is trying to figure out how to implement it without a bunch of rules that people would have to follow and remember.

eg. all validations need to be after struct specific tags such as structonly and nostructlevel but that's not always true as exists, omitempty and required can and should be used before the struct specific tags.

I'm just worried that it will make the rules for using validations on structs so complex that it will make validator less user friendly.

What do you think, would the example above be confusing or hard to remember? or am I just being pedantic?

Hi @joeybloggs

Funny - in the interest of opensourcedness, I was looking at this myself yesterday - and had an approximation working where I'd updated traverseField to just drop through after doing the traverseStruct so it would effectively call the per-field registered validator on the nested struct field.

I got a little unstuck though after running the UTs and realizing it was a little more complicated than I'd hoped :-) For example, I think I had a field that was a struct pointer that had an required flag that had the HasValue() called on the structure rather than on the pointer.... I shelved it at that point to re-investigate when I had a little more time.

From my perspective, I'd imagine a field that has a validator declared in the tag, that validator should be called against the field value - whether it is a structure or a map or a string etc. From my limited understanding though - it doesn't feel like it's possible without special casing some of the existing builtins -- but I'm not too sure about that.

I was wondering if a pragmatic solution would be to introduce another keyword like "dive" but this time to say - validate this structure as a field? As with dive - you can add another validator entry to say and this is the validator to use. The advantage of this is that it is a user buy-in and there shouldn't be any risk of existing structures that happen to "accidentally" specify a validator on a structure field failing validation suddenly (unless the keyword that is chosen conflicts with their validator name)

Hey @robbrockbank

I agree there are a few things that can be done to make it work, that was never in doubt, however all idea's that I can come up with would make it a little more confusing to use; I could eliminate the confusion and make it easy, but it would require some breaking changes.

So I think that, If you can live with Struct Level Validation for now, I will add this to the list of features for v9 where it can be added in a better manner better.

It will take a while to fully complete v9, but I think it will be worth it for all.

please let me know of any other changes that you may like to see and I'll also try and see what I can do for v9

Hey @robbrockbank after allot of tinkering and feedback from other users I will probably not be implementing this feature; it's just too much of a one off that really affects performance and ease of use.

Was this page helpful?
0 / 5 - 0 ratings