为 Bson.M mongodb 创建自定义 mashler/unmashler 时出错

Ach*_*old 5 marshalling go unmarshalling mongodb

WriteValueBytes can only write while positioned on a Element or Value but is positioned on a TopLevel尝试为 bson.M 创建自定义 mashler/unmashler 时出现错误

我有一个名为 TransactionId 的自定义类型,它代表一个 UUID,我想在存储到 monbodb 之前将此值转换为字符串,并在从 mongodb 提取值时将其从字符串转换回来。

这是我到目前为止的代码

package main

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

// TransactionID is a UUID used to trace a batch of work which is being processed.
type TransactionID uuid.UUID

// String returns the transaction id as a string
func (id TransactionID) String() (result string, err error) {
    val, err := uuid.FromBytes(id[:])
    if err != nil {
        return result, errors.Wrapf(err, "cannot convert transaction ID %s to UUID", string(id[:]))
    }
    return val.String(), nil
}

func (id TransactionID) MarshalBSONValue() (bsontype.Type, []byte, error) {
    idString, err :=  id.String()
    if err != nil {
        return bsontype.String, nil, err
    }
    return bsontype.String, bsoncore.AppendString(nil, idString), nil
}


func (id *TransactionID) UnmarshalBSONValue(bsonType bsontype.Type, bytes []byte) error {
    uid, err := uuid.FromBytes(bytes)
    if err != nil {
        return err
    }

    *id = TransactionID(uid)
    return nil
}


func NewTransactionID() TransactionID {
    return TransactionID(uuid.New())
}


func main() {
    id := NewTransactionID()

    _, err :=  bson.Marshal(id)
    if err != nil {
        log.Fatal(err)
    }
}
Run Code Online (Sandbox Code Playgroud)

我正在执行WriteValueBytes can only write while positioned on a Element or Value but is positioned on a TopLevel解组步骤。

链接: https: //play.golang.org/p/_n7VpX-KIyP

Wan*_*iar 4

我发现 WriteValueBytes 只能在定位在元素或值上时写入,但在解组步骤中定位在顶层上。

函数bson.Marshal()需要一个可以转换为文档的参数(即interface{})。这就是错误消息与值的位置相关的原因。即,文档的顶层不能有字符串,它必须是文档的元素。如果您需要封送单个值,您应该使用bson.MarshalValue()代替。

id := NewTransactionID()
vtype, vdata, err := bson.MarshalValue(id)
Run Code Online (Sandbox Code Playgroud)

使用的示例bson.Marshal()如下(添加到您的示例中):

type Foo struct {
    ID TransactionID
}

func main() {
    id := NewTransactionID()
    foo, err :=  bson.Marshal(&Foo{ID:id})
    if err != nil {
        panic(err)
    }
}
Run Code Online (Sandbox Code Playgroud)