[Golang] 構造体 in 構造体のバリデーションについて


GolangのORMライブラリGORMで、モデルの関連づけを表現した際のバリデーションにつまづいたのでメモ。

使用ライブラリ群

困ったこと

GORMで以下のようなHasOne関係のモデルを作り、それぞれの構造体にvalidateタグを付与している状況。

type User struct {
    ID        int       `json:"id" gorm:"primary_key"`
    Email     string    `json:"email" validate:"email,required,max=255"`
    Password  string    `json:"password" validate:"required,min=8,max=16"`
    Profile   Profile   `json:"profile" gorm:"foreignKey:ID"`
}

type Profile struct {
    ID        int       `json:"id" gorm:"primary_key"`
    UserID    int       `json:"userId" validate:"required"`
    Name      string    `json:"name" validate:"required,max=255"`
    Hobby     string    `json:"hobby"`
}

UserのみのCreate(Profileは作らない。Save前にValidation実行)をするAPIを用意し、以下のパラメーターをPOSTすると、

{
    "email": "[email protected]",
    "password": "hogehoge"
}

以下のようなバリデーションエラーとなる。

Key: 'User.Profile.UserID' Error:Field validation for 'UserID' failed on the 'required' tag
Key: 'User.Profile.Name' Error:Field validation for 'Name' failed on the 'required' tag

原因は単純で、Userに埋め込んでるProfileのvalidateタグも見にいってるので、バリデーションエラーとなる。困った。

解決策

validatorのリファレンスを探ってると、Skip Fieldなるものを発見。

validate:"-"で検証をスキップできるみたい。User.Profileに追記する。

type User struct {
    ID        int       `json:"id" gorm:"primary_key"`
    Email     string    `json:"email" validate:"email,required,max=255"`
    Password  string    `json:"password" validate:"required,min=8,max=16"`
    Profile   Profile   `json:"profile" gorm:"foreignKey:ID" validate:"-"` // ココに追記した
}
...

Profileの検証がスキップされてUserの作成に成功。

気付き

  • jsonタグでも"-"(ハイフン)でフィールドが無視できたと思うので、struct tagsのvalueにおける"-"は無視する的な使い方をするっぽい?