この投稿で使用している言語、ライブラリのバージョン
- Go v1.17.1
- github.com/go-playground/validator v10.9.0
やりたいこと
github.com/go-playground/validatorで構造体をバリデーションした場合、
エラーの中には以下のように構造体のフィールド名が埋め込まれています。
main.go
package main
import (
"fmt"
"strings"
"github.com/go-playground/validator/v10"
)
type Person struct {
Name string `json:"name" validate:"required,max=100"`
Email string `json:"email" validate:"required,email"`
}
func main() {
p := Person{
Name: strings.Repeat("x", 101),
Email: "aa.bb",
}
validate := validator.New()
if err := validate.Struct(p); err != nil {
errs := err.(validator.ValidationErrors)
for _, errrs := range errs {
fmt.Printf("Field=%s, Tag=%s\n", errrs.Field(), errrs.Tag())
}
}
}
$ go run main.go
Field=Name, Tag=max
Field=Email, Tag=email
バリデーションエラーの結果をAPIのレスポンスとして返す場合に、構造体のフィールド名ではなく、jsonタグの名前で返したかったので方法を調べました。
解決策
ドキュメントにそのものズバリ書いてありました。
func (*Validate) RegisterTagNameFunc
RegisterTagNameFuncを使うことで、エラーフィールドを取得する際にjsonタグ名を取得することができます。
main.go
package main
import (
"fmt"
"reflect"
"strings"
"github.com/go-playground/validator/v10"
)
type Person struct {
Name string `json:"name" validate:"required,max=100"`
Email string `json:"email" validate:"required,email"`
}
func main() {
p := Person{
Name: strings.Repeat("x", 101),
Email: "aa.bb",
}
validate := validator.New()
validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0] // jsonタグ名を取得する
if name == "-" {
return ""
}
return name
})
if err := validate.Struct(p); err != nil {
errs := err.(validator.ValidationErrors)
for _, errrs := range errs {
fmt.Printf("Field=%s, Tag=%s\n", errrs.Field(), errrs.Tag())
}
}
}
$ go run main.go
Field=name, Tag=max
Field=email, Tag=email