Issue
Using gopkg.in/mgo.v2/bson
, I wonder how to marshal an interface{} value into a value of type bson.Raw
.
The documentation for bson.Raw
states:
Using this type it is possible to unmarshal or marshal values partially.
But I can’t find a Marshal function that would return bson.Raw
.
What am I missing?
Example of what I try to do:
package main
import (
"fmt"
"gopkg.in/mgo.v2/bson"
)
func main() {
// How to avoid a MarshalRaw help function?
raw, err := MarshalRaw("Hello world")
if err != nil {
panic(err)
}
fmt.Printf("%+v\n", raw)
}
func MarshalRaw(v interface{}) (*bson.Raw, error) {
bin, err := bson.Marshal(struct{ Raw interface{} }{v})
if err != nil {
return nil, err
}
var raw struct{ Raw bson.Raw }
err = bson.Unmarshal(bin, &raw)
if err != nil {
return nil, err
}
return &raw.Raw, nil
}
Output:
&{Kind:2 Data:[12 0 0 0 72 101 108 108 111 32 119 111 114 108 100 0]}
Solution
bson.Raw is used as a value both when marshaling and unmarshaling.
To transform an interface{}
into a bson.Raw
, the first thing to do is to marshal it so that you get the plain document data that represents whatever is being marshaled:
var value interface{} = bson.M{"some": "value"}
data, err := bson.Marshal(value)
if err != nil {
log.Fatal(err)
}
and then it may have one or more fields unmarshaled into bson.Raw
values:
var doc struct{ Some bson.Raw }
err = bson.Unmarshal(data, &doc)
if err != nil {
log.Fatal(err)
}
or even the entire document:
var doc bson.Raw
err = bson.Unmarshal(data, &doc)
if err != nil {
log.Fatal(err)
}
If you want the entire document rather than just a field, you can also use this shortcut:
doc := bson.Raw{3, data}
The 3 constant represents a document in the bson specification, and it must of course match the provided data. Since BSON only supports documents at the top level, we know this must be correct.
Answered By – Gustavo Niemeyer
Answer Checked By – Robin (GoLangFix Admin)