I have a custom type for the purposes of formatting a time object
type MyTime time.Time
To use this with JSON I have implemented:
func (t *MyTime) UnmarshalJSON(b []byte) error
func (t MyTime) MarshalJSON() ([]byte, error)
These functions marshal the type to/from a formatted string and work fine. I now need to read/write this field to/from mongoDb. I have implemented
func (t *MyTime) UnmarshalBSON(b []byte) error
Which lets me read my type from mongo with no trouble (mongo doc has same format as above). this implementation simply strips the size and trailing zero bytes from the BSON string and parses as for JSON. So far so good My issue is how I write this value in the same format. I started by implementing:
func (t MyTime) MarshalBSON() ([]byte, error)
with a reversal of the unmarshal above (inserting size and trailing zero) and verified that the byte slice was identical to that I read earlier but this generated an error. Unlike the JSON version, the MarshalBSON implementation will not allow me to write a string. Debugging into the mgo library shows that it is expecting me to marshal a structure, not a string field. After googling the problem, I tried implementing
func (t *MyTime) GetBSON() (output interface{}, err error)
But this is not called by the InsertIntoMongo code. There are multiple ways of marshalling the object but this format is defined externally and I cannot change it.
How can I achieve this last piece of the puzzle? Namely, make BSON marshal my custom type as a string value (the reverse of the unmarshal already implemented)
edit: My implementation of MarshalBSON mirrored the JSON as a reverse of Unmarshal. In JSON unmarshal is passed a string (as []byte), Marshal returns the same string. In BSON, unmarshal is passed size (4 bytes = len(string) + 1) + string + \x00. Marshal returns the same stream (verified as identical)
the call
mongoClient.Database.Collection.InsertOne(ctx, data, nil)
Where data is a structure containing a number of instances of MyTime
error = go.mongodb.org/mongo-driver/mongo.CommandError
error.Code = 22
error.Name = InvalidBSON
error.Message = invalid bson type in element with field name '021-07-16T09:12:31.793395300' in object with _id: "..."
(The field name is the string value I tried to write with the first character (byte) missing) It should be a string, not a field With the Marshal Function missing, the parent element (MyTime) was written to mongo as an (empty) object where it should be a string.
Slighty old question, but in case its of help...
MarshalBSON()andUnmarshalBSON()are really for things that marshal/unmarshal to BSON document. Whereas, yourtype MyTime time.Timeis probably better marshalled/unmarshalled as a BSON value - for which there are specific methods that need to be implemented, e.g.