如何将具有自定义 MarshalBSONValue 的结构的 nil 指针序列化为 BSON?

How to serialize nil pointer of structure with custom MarshalBSONValue into BSON?

mongodb我程序中使用的官方golang驱动


package main

import (
    "fmt"
    "github.com/pkg/errors"
    "go.mongodb.org/mongo-driver/bson"
    "go.mongodb.org/mongo-driver/bson/bsontype"
    "go.mongodb.org/mongo-driver/x/bsonx"
    "go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
    "log"
    "strconv"
)

type Bar struct {
    a int64
}

func (b Bar) MarshalBSONValue() (bsontype.Type, []byte, error) {
    return bsonx.String(fmt.Sprintf("%d", b.a)).MarshalBSONValue()
}

func (b *Bar) UnmarshalBSONValue(t bsontype.Type, data []byte) error {
    if t != bsontype.String {
        return errors.Errorf("bsontype(%s) not allowed in Bar.UnmarshalBSONValue, only string accept", t.String())
    }
    str, _, ok := bsoncore.ReadString(data)
    if !ok {
        return errors.Errorf("decode string, but string not found")
    }

    dec, err := strconv.ParseInt(str, 10, 64)
    if err != nil {
        return err
    }
    b = &Bar{a:dec}
    return nil
}

type Foo struct {
    Bar *Bar`bson:"Bar, omitempty"`
}

func main() {
    f := Foo{}
    _, err := bson.Marshal(f)
    if err != nil {
        log.Fatalf("Failed to marshal. Error: %v", err)
    }
}

此程序将因错误而崩溃:

panic: value method main.Bar.MarshalBSONValue called using nil *Bar pointer

goroutine 1 [running]:
main.(*Bar).MarshalBSONValue(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
        <autogenerated>:1 +0x87
reflect.Value.call(0x11ebc60, 0xc000010330, 0x293, 0x1218915, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
        /usr/local/go/src/reflect/value.go:447 +0x461

您需要删除 omitempty 之前的 space:

type Foo struct {
    Bar *Bar`bson:"Bar,omitempty"`
}

解析器无法处理", omitempty",因为代码如下:

for idx, str := range strings.Split(tag, ",") {
        if idx == 0 && str != "" {
            key = str
        }
        switch str {
        case "omitempty":