Mgo SetBSON to mongo golang driver

I’m migration our app from mgo to the official mongo go driver, but I’m stuck with the mgo SetBSON migration, this is my old code and I don’t know how to do this using the new driver:

type MyStruct struct {
	ID            primitive.ObjectID `bson:"_id"`
	Ends          time.Time          `bson:"ends"`
}
func (st *MyStruct) SetBSON(raw bson.Raw) error {
	decoded := new(struct {
		ID            primitive.ObjectID `bson:"_id"`
		Ends          string             `bson:"ends"`
	})

	bsonErr := raw.Unmarshal(decoded)
	if bsonErr != nil {
		return bsonErr
	}

	const dateFormat = "2006-01-02"
	
	end, endErr := time.ParseInLocation(dateFormat, decoded.Ends, constants.NYCLoc)
	if endErr != nil {
		return endErr
	}

	st.ID = decoded.ID
	st.Ends = time.Date(ey, em, ed, 23, 59, 0, 0, constants.NYCLoc)
	return nil
}

The core is, we have a struct that in mongo stores the “end” field as a string that looks like “20200402”. When the driver reads the bson from mongo, I need to decode the struct and convert the string value from the field “end” into a time.Time Go type.

I hope I can avoid having to create a new custom “field” type for the end mongo field, because the app assumes a time.Time all over.

Thanks

Hi @Diego_Medina,

You can do this using the UnmarshalBSON hook for the driver. This is similar to the UnmarshalJSON hook in the encoding/json library. I wrote up an example of this in Go Playground - The Go Programming Language. It’s worth noting that version 1.3.0 of the driver introduced a custom BSON registry to mimic parts of mgo BSON behavior to mitigate BSON issues for users when migrating to the official driver. This registry supports GetBSON/SetBSON. You can see documentation for that at mgocompat package - go.mongodb.org/mongo-driver/bson/mgocompat - Go Packages.

2 Likes

Thanks you! your example was just what I needed.

I was trying to understand why not use the bsoncodec package - go.mongodb.org/mongo-driver/bson/bsoncodec - Go Packages.

Is this what you mean by

It’s worth noting that version 1.3.0 of the driver introduced a custom BSON registry

@Yehuda_Makarov You can use the bsoncodec package and write a custom codec for this use case, but implementing the bson.Unmarshaler interface works just as well.

Version 1.3.0 of the driver introduced a new mgocompat package that provides a custom BSON registry (mgocompat.Registry) to mimic some of mgo’s BSON behavior. This includes adding support for GetBSON and SetBSON methods. You can see more details about it at mgocompat package - go.mongodb.org/mongo-driver/bson/mgocompat - Go Packages. Search for Setter on that page to see how the SetBSON method should be implemented. If you choose to use this registry, you can enable it for a Client as follows:

opts := options.Client().SetRegistry(mgocompat.Registry)
client, err := mongo.Connect(ctx, opts)
// handle err, defer Disconnect(), etc

Feel free to add another comment here or open a new question on these forums if you have any follow-up questions about the new registry.

– Divjot

2 Likes