1

I'm using MarshalBSONValue to marshal an inner struct field to a custom string representation.

I can't figure out how to implement the inverse operation, UnmarshalBSONValue, in order to parse the custom string representation into an inner struct.

import (
    "fmt"
    "testing"

    "github.com/stretchr/testify/assert"
    "go.mongodb.org/mongo-driver/bson"
    "go.mongodb.org/mongo-driver/bson/bsontype"
)

type inner struct {
    value string
}

func (i inner) MarshalBSONValue() (bsontype.Type, []byte, error) {
    return bsontype.String, []byte(i.value), nil
}

// How to implement this?
//
// func (i *inner) UnmarshalBSONValue(t bsontype.Type, data []byte) error {
//     ...
// }

type Outer struct {
    Inner inner `bson:"inner"`
}

func TestMarshalBSON(t *testing.T) {
    var outer1 = Outer{Inner: inner{value: "value"}}
    doc, err := bson.Marshal(outer1)
    assert.NoError(t, err)
    fmt.Printf("%#v\n", string(doc)) // "\x11\x00\x00\x00\x02inner\x00value\x00"

    var outer2 Outer
    err = bson.Unmarshal(doc, &outer2) // error
    assert.NoError(t, err)

    assert.Equal(t, outer1, outer2)
}

I would greatly appreciate it if anyone could provide a working implementation of UnmarshalBSONValue for the example test above.

1 Answer 1

5

You can use bsoncore.ReadString to parse the given value.

func (i inner) MarshalBSONValue() (bsontype.Type, []byte, error) {
    return bson.MarshalValue(i.value)
}

func (i *inner) UnmarshalBSONValue(t bsontype.Type, value []byte) error {
    if t != bsontype.String {
        return fmt.Errorf("invalid bson value type '%s'", t.String())
    }
    s, _, ok := bsoncore.ReadString(value)
    if !ok {
        return fmt.Errorf("invalid bson string value")
    }

    i.value = s
    return nil
}
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks! However UnmarshalBSONValue does not seem to be called using the test method above.
@titaniumdecoy it works for me: play.golang.org/p/zidkH4NIZpn
Ah, I see my implementation of MarshalBSONValue was incorrect. Thanks so much!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.