Open shuqingzai opened 1 year ago
Hi @shuqingzai, and thanks for the feedback! If you only need to support a single language, for now I'd recommend creating a custom constraint so that you can control the message. Will explore options with the team (exposing the FieldConstraints
shouldn't be too difficult).
you can get it, but with ugly reflection code
func main() {
msg := &pb.PageParams{
Page: 0,
PageSize: 10,
}
v, err := protovalidate.New()
if err != nil {
fmt.Println("failed to initialize validator:", err)
}
if err = v.Validate(msg); err != nil {
var valErr *protovalidate.ValidationError
if ok := errors.As(err, &valErr); ok {
errPb := valErr.ToProto()
fmt.Printf("\n%+v\n\n", errPb.GetViolations())
a := errPb.GetViolations()[0]
fieldDesc := msg.ProtoReflect().Descriptor().Fields().ByTextName(a.FieldPath)
// import "buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go/buf/validate"
typeDesc := (*validate.E_Field).TypeDescriptor()
x := fieldDesc.Options().ProtoReflect().Get(typeDesc).Message().Interface().(*validate.FieldConstraints)
fmt.Println(x.Type) // type is oneof
fmt.Println(*(x.Type.(*validate.FieldConstraints_Uint32).Uint32.Lte))
}
}
}
you can get it, but with ugly reflection code
func main() { msg := &pb.PageParams{ Page: 0, PageSize: 10, } v, err := protovalidate.New() if err != nil { fmt.Println("failed to initialize validator:", err) } if err = v.Validate(msg); err != nil { var valErr *protovalidate.ValidationError if ok := errors.As(err, &valErr); ok { errPb := valErr.ToProto() fmt.Printf("\n%+v\n\n", errPb.GetViolations()) a := errPb.GetViolations()[0] fieldDesc := msg.ProtoReflect().Descriptor().Fields().ByTextName(a.FieldPath) // import "buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go/buf/validate" typeDesc := (*validate.E_Field).TypeDescriptor() x := fieldDesc.Options().ProtoReflect().Get(typeDesc).Message().Interface().(*validate.FieldConstraints) fmt.Println(x.Type) // type is oneof fmt.Println(*(x.Type.(*validate.FieldConstraints_Uint32).Uint32.Lte)) } } }
@MarcusMogg
Your approach is possible, but when v.Validate()
is used, reflection has already been performed. If protovalidate natively supports it, it will definitely be better for performance and scalability. Other languages can also enjoy such convenience
you can get it, but with ugly reflection code
func main() { msg := &pb.PageParams{ Page: 0, PageSize: 10, } v, err := protovalidate.New() if err != nil { fmt.Println("failed to initialize validator:", err) } if err = v.Validate(msg); err != nil { var valErr *protovalidate.ValidationError if ok := errors.As(err, &valErr); ok { errPb := valErr.ToProto() fmt.Printf("\n%+v\n\n", errPb.GetViolations()) a := errPb.GetViolations()[0] fieldDesc := msg.ProtoReflect().Descriptor().Fields().ByTextName(a.FieldPath) // import "buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go/buf/validate" typeDesc := (*validate.E_Field).TypeDescriptor() x := fieldDesc.Options().ProtoReflect().Get(typeDesc).Message().Interface().(*validate.FieldConstraints) fmt.Println(x.Type) // type is oneof fmt.Println(*(x.Type.(*validate.FieldConstraints_Uint32).Uint32.Lte)) } } }
@MarcusMogg
Your approach is possible, but when
v.Validate()
is used, reflection has already been performed. If protovalidate natively supports it, it will definitely be better for performance and scalability. Other languages can also enjoy such convenience
Using reflection is inevitable when you append fields (so many rules here). Perhaps a custom error message formatter interface for rules would suit your needs better?
I18n for fields validating is very necessary. I hope this package can handle it gracefully.
Feature description:
Example Proto
go validate
When I validate, the error returned by
page
is*validate.Violation
, but I can’t get the request value0
and the rule values:0
and1000
, can the package add new fields (value
andattributes
?? ) return?Problem it solves or use case:
Users can get these values for more custom operations
I need to perform
i18n
now, because the semantics of each language are different when translating, and I need to customize the translation, but I can’t get these values, which makes the work very difficultProposed implementation or solution:
Contribution:
Examples or references:
Additional context: