首页 > 后端开发 > Golang > 在 Go 中解组 MongoDB 文档时如何忽略空值?

在 Go 中解组 MongoDB 文档时如何忽略空值?

Susan Sarandon
发布: 2025-01-02 16:23:07
原创
856 人浏览过

How to Ignore Null Values When Unmarshalling MongoDB Documents in Go?

在 MongoDB 文档解组期间忽略空值

将 MongoDB 文档解组到包含不可为空字符串字段的 Go 结构时,遇到 null文档中的值可能会导致错误。为了解决这个问题,有必要找到一种方法在解组过程中忽略这些空值。

使用自定义解码器

处理空值的一种方法是为字符串类型创建自定义解码器。此自定义解码器将识别空值并通过将相应字段设置为空字符串来处理它们,从而有效地忽略空值:

import (
    "go.mongodb.org/mongo-driver/bson/bsoncodec"
    "go.mongodb.org/mongo-driver/bson/bsonrw"
    "go.mongodb.org/mongo-driver/bson/bsontype"
)

type nullawareStrDecoder struct{}

func (nullawareStrDecoder) DecodeValue(dctx bsoncodec.DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
    if !val.CanSet() || val.Kind() != reflect.String {
        return errors.New("bad type or not settable")
    }
    var str string
    var err error
    switch vr.Type() {
    case bsontype.String:
        if str, err = vr.ReadString(); err != nil {
            return err
        }
    case bsontype.Null:
        if err = vr.ReadNull(); err != nil {
            return err
        }
    default:
        return fmt.Errorf("cannot decode %v into a string type", vr.Type())
    }

    val.SetString(str)
    return nil
}
登录后复制

然后可以使用 bsoncodec.Registry 注册此自定义解码器并应用于一个 mongo.Client 对象:

clientOpts := options.Client().
    ApplyURI("mongodb://localhost:27017/").
    SetRegistry(
        bson.NewRegistryBuilder().
            RegisterDecoder(reflect.TypeOf(""), nullawareStrDecoder{}).
            Build(),
    )
client, err := mongo.Connect(ctx, clientOpts)
登录后复制

创建类型中立的 Null-Aware解码器

要处理多种类型的空值,可以创建一个类型中立的解码器来检查空值,如果遇到空值,则将相应字段设置为其零值类型:

type nullawareDecoder struct {
    defDecoder bsoncodec.ValueDecoder
    zeroValue  reflect.Value
}

func (d *nullawareDecoder) DecodeValue(dctx bsoncodec.DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
    if vr.Type() != bsontype.Null {
        return d.defDecoder.DecodeValue(dctx, vr, val)
    }

    if !val.CanSet() {
        return errors.New("value not settable")
    }
    if err := vr.ReadNull(); err != nil {
        return err
    }

    val.Set(d.zeroValue)
    return nil
}
登录后复制

此解码器可以使用 bsoncodec 注册。特定类型或所有类型的注册表:

customValues := []interface{}{
    "",       // string
    int(0),   // int
    int32(0), // int32
}

rb := bson.NewRegistryBuilder()
for _, v := range customValues {
    t := reflect.TypeOf(v)
    defDecoder, err := bson.DefaultRegistry.LookupDecoder(t)
    if err != nil {
        panic(err)
    }
    rb.RegisterDecoder(t, &nullawareDecoder{defDecoder, reflect.Zero(t)})
}
登录后复制

以上是在 Go 中解组 MongoDB 文档时如何忽略空值?的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板