Marshal into a bson.Raw

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)

Leave a Reply

Your email address will not be published.