Dr.Nemo
Dr.Nemo

Reputation: 1491

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

mongodb official golang dirver used in my program.


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)
    }
}

this program will panic with error:

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

Upvotes: 0

Views: 1092

Answers (1)

Burak Serdar
Burak Serdar

Reputation: 51467

You need to remove the space before omitempty:

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

The parser cannot handle ", omitempty", because the code is as folllows:

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

Upvotes: 1

Related Questions