-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Allow ValidationErrors type to be used externally #420
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The `ValidationErrors` type is public, but inside its 2 functions it casts to the private `fieldError`. Since there is no way to access the `fieldError` outside this package it meant creating and using `ValidationErrors` outside this package was impossible. My use case is for testing, I'm trying to test how my code behaves when various `ValidationErrors` are returned without needing to actually setup data to fail in the various ways.
Translate also needed the `ns` field.
| Translate(ut ut.Translator) string | ||
|
|
||
| // Error returns the FieldError's error message | ||
| Error() string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @joshhsoj1902 thanks for the PR
I think that only this addition is necessary
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @joeybloggs, I might be doing something wrong on my end, But for me, it only works when I also change the *fieldError references to the interface. When I just add Error() string to the interface I still get this error thrown
panic: interface conversion: validator.FieldError is *validator.fakeFieldError, not *validator.fieldError
(that panic happens on line 51, fakeFieldError is my implentation of FieldError)
My understanding is that since line 51 is trying to cast to the private struct, the only way the casting will pass is if the object being cast was also made from that private struct. and since it's private, I have no way of actually doing that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll take a closer look, sorry for the delay I'm extremely busy
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No problem at all. If there is anything you would rather I do instead, let me know. I think there are a few ways to solve this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@joshhsoj1902 would you be able to share your example, seems like the best place for me to start :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey Joey, sorry for the slow reply. I do plan on circling back and creating a small sample program for you. Time is always the issue. Things should slow down a bit for me after next week.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no worries I only get a couple hours at most to take care of my open source stuff lately, tis the holiday season.
|
Hey @joshhsoj1902 I would be very interested in seeing your example that fails, I was able to cast the error to the field error type, see modified simple example below; strangely enough, I was unable to cast to the interface type in the range itself, had to be after the variable was already extracted. package main
import (
"fmt"
"reflect"
validator "gopkg.in/go-playground/validator.v9"
)
// User contains user information
type User struct {
FirstName string `validate:"required"`
LastName string `validate:"required"`
Age uint8 `validate:"gte=0,lte=130"`
Email string `validate:"required,email"`
FavouriteColor string `validate:"iscolor"` // alias for 'hexcolor|rgb|rgba|hsl|hsla'
Addresses []*Address `validate:"required,dive,required"` // a person can have a home and cottage...
}
// Address houses a users address information
type Address struct {
Street string `validate:"required"`
City string `validate:"required"`
Planet string `validate:"required"`
Phone string `validate:"required"`
}
// use a single instance of Validate, it caches struct info
var validate *validator.Validate
func main() {
validate = validator.New()
validateStruct()
validateVariable()
}
func validateStruct() {
address := &Address{
Street: "Eavesdown Docks",
Planet: "Persphone",
Phone: "none",
}
user := &User{
FirstName: "Badger",
LastName: "Smith",
Age: 135,
Email: "[email protected]",
FavouriteColor: "#000-",
Addresses: []*Address{address},
}
// returns nil or ValidationErrors ( []FieldError )
err := validate.Struct(user)
if err != nil {
// this check is only needed when your code could produce
// an invalid value for validation such as interface with nil
// value most including myself do not usually have code like this.
if _, ok := err.(*validator.InvalidValidationError); ok {
fmt.Println(err)
return
}
for _, err := range err.(validator.ValidationErrors) {
e2 := err.(validator.FieldError)
fmt.Println(reflect.TypeOf(e2))
fmt.Println(e2.Namespace())
fmt.Println(e2.Field())
fmt.Println(e2.StructNamespace()) // can differ when a custom TagNameFunc is registered or
fmt.Println(e2.StructField()) // by passing alt name to ReportError like below
fmt.Println(e2.Tag())
fmt.Println(e2.ActualTag())
fmt.Println(e2.Kind())
fmt.Println(e2.Type())
fmt.Println(e2.Value())
fmt.Println(e2.Param())
fmt.Println()
}
// from here you can create your own error messages in whatever language you wish
return
}
// save user to database
}
func validateVariable() {
myEmail := "joeybloggs.gmail.com"
errs := validate.Var(myEmail, "required,email")
if errs != nil {
fmt.Println(errs) // output: Key: "" Error:Field validation for "" failed on the "email" tag
return
}
// email ok, move on
} |
|
@joshhsoj1902 are you able to provide an example? |
|
Hey @deankarn, Sorry for never getting back to you on this, I ended up changing projects and the code I was dealing with I no longer have access to. I would need to come up with a new example and honestly, I don't foresee myself having time to do that anytime soon. I'm really sorry, I hate not being able to help out more :(. Feel free to close this. |
|
I you ever do find time or want to pursue again please don't hesitate to revive this @joshhsoj1902 :) |
|
I've also run into the desire to include the |
The
ValidationErrorstype is public, but inside its 2 functions it casts to the privatefieldError. Since there is no way to access thefieldErroroutside this package it meant creating and usingValidationErrorsoutside this package was impossible.My use case is for testing, I'm trying to test how my code behaves when various
ValidationErrorsare returned without needing to actually setup data to fail in the various ways.Fixes Or Enhances # .
Make sure that you've checked the boxes below before you submit PR:
Change Details:
@go-playground/admins