mongodb - Go 官方 mongo-driver 中如何实现结构体字段验证?

标签 mongodb validation go mongo-go

我正在使用 Go 官方 MongoDB 驱动程序。有没有办法使用 BSON 标签验证结构字段,就像 GORM pkg 那样?

enter image description here

最佳答案

你的意思是作为结构标签?不,不是直接。这是有充分理由的:软件库越来越多地采用“做一件事并做好”的方法。换句话说:使用正确的工具来完成工作。

但是验证你的结构很容易。您可以利用强大的github.com/asaskevich/govalidator ,例如:

package main

import (
    "testing"

    "github.com/asaskevich/govalidator"
    "go.mongodb.org/mongo-driver/bson/primitive"
)

type Author struct {
    FirstName string `valid:"stringlength(3|20)" bson:"given_name" json:"given_name"`
    LastName  string `valid:"stringlength(2|20)" bson:"surname" json:"surname"`
}

type Book struct {
    // Here, if ID is set, it needs to be a valid ObjectID
    ID     primitive.ObjectID `valid:"oid,optional" bson:"_id,omitempty" json:"_id,omitempty"`
    ISBN   string             `valid:"isbn13,optional" bson:"isbn,omitempty" json:"isbn,omitempty"`
    Title  string             `valid:"stringlength(5|20)" bson:"title" json:"title"`
    // This instructs govalidator to validate the referenced struct, even when
    // it is a pointer
    Author *Author            `valid:"" bson:"author" json:"author"`
}



// ObjectIDValidator validates whether the given type is a primitive.ObjectId
// and whether its value is valid.
// govalidator only validates a string as ObjectId, so we implement a little wrapper function...
func ObjectIDValidator(inner, outer interface{}) bool {
    oid := inner.(primitive.ObjectID)
    str := oid.Hex()
    return govalidator.IsMongoID(str)
}

// ...and add it to the validators you can use as a struct tag
func init() {
    govalidator.CustomTypeTagMap.Set("oid", govalidator.CustomTypeValidator(ObjectIDValidator))
}

func TestValidity(t *testing.T) {
    testCases := []struct {
        desc         string
        book         Book
        expectedFail bool
    }{
        {
            desc: "A book with an invalid ISBN",
            book: Book{
                ID:     primitive.NewObjectID(),
                Title:  "foobar",
                ISBN:   "abc",
                Author: &Author{FirstName: "Foo", LastName: "Bar"},
            },
            expectedFail: true,
        },
        {
            desc: "A perfectly valid (and good!) book",
            book: Book{
                ID:     primitive.NewObjectID(),
                Title:  "Neuromancer",
                ISBN:   "978-0441569595",
                Author: &Author{FirstName: "William", LastName: "Gibson"},
            },
            expectedFail: false,
        },
        {
            desc: "Still a good book, but with the title cut short",
            book: Book{
                ID:     primitive.NewObjectID(),
                Title:  "Neur",
                ISBN:   "978-0441569595",
                Author: &Author{FirstName: "William", LastName: "Gibson"},
            },
            expectedFail: true,
        },
        {
            desc: "Still a good book, only the author's name was cut short",
            book: Book{
                ID:     primitive.NewObjectID(),
                Title:  "Neuromancer",
                ISBN:   "978-0441569595",
                Author: &Author{FirstName: "W", LastName: "Gibson"},
            },
            expectedFail: true,
        },
    }
    for _, tC := range testCases {
        t.Run(tC.desc, func(t *testing.T) {
            ok, err := govalidator.ValidateStruct(tC.book)

            switch {
            case !ok && !tC.expectedFail:
                t.Errorf("%#v unexpectedly did not validate as a Book: %s", tC.book, err)
                return
            case ok && tC.expectedFail:
                t.Errorf("%#v unexpectedly validated as a Book!", tC.book)
                return
            case (!ok && tC.expectedFail) || (ok && !tC.expectedFail):
                t.Logf("Just as planned")
            }

        })
    }
}

关于mongodb - Go 官方 mongo-driver 中如何实现结构体字段验证?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62976721/

相关文章:

go - 如何在 Go 中提供可选参数?

javascript - 如何使用同一记录中的现有值更新 MongoDB 记录

go - Google BigQuery本地模拟

mongodb - 如何推迟 mgo session ,直到它完全流式传输到客户端?

c# - 用于电子邮件或电话的 ASP.NET MVC 数据注释验证器

validation - 在 View 中呈现验证错误,避免重复

javascript - 字段集的 Angular Group 验证

mysql - 如何在 golang 中编写一个通用方法以在任何 mysql 表中插入记录

node.js - 如何从 Angular 发送https post请求?

node.js - 如何在两个包中使用 Mongoose ?