Extended JSON Struct Tags

Hi Team, thanks for all the work on the driver! Much appreciated!

One of the things that can be improved in the driver in my opinion is the type leakage. The driver has an internal type system that is sort of forced onto users. primitive.ID is the most common example. Rather than hiding that fact that mongo runs on [12]byte ids internally, the hex string <–> [12]byte conversion and error handling is pushed out to library users. Ostensibly this is because bson != json, but, at some point all we care about is json–that’s what we are sending across the internet. So, this conversion between bson/extended json/json has become the responsibility of the developer using mongo.

Because it complicates writing, testing, and debugging the business logic, I have a strong preference to push this conversion as close to the database layer as possible. That way the json-to-bson and bson-to-json is happening in one place and isn’t strewn throughout other data manipulation code.

Ok there are my reasons haha, thanks for getting this far. My suggestion to fix this problem is to implement extended json struct tags. Like this:

type User struct {
    ID string             `bson:"id,$oid"`
    Name string           `bson:"id"`
    DateOfBirth int       `bson:"dob,$date,omitemtpy"`
    LastLogin *time.Time  `bson:"lastLogin,$timestamp,omitempty"` 

Struct tags formatted in this way could serve the same purpose as extended json. The json <-> bson translation information is just listed in the struct rather than in UnmarshalBSON functions, or decoders, or extended json translation functions. In tests this would allow users to work with these structs as they would any other. The use of go’s type system in the structs keeps them working with all the other go libraries out there. Let me know if you have any questions. Also, I’d be happy to help write this.

1 Like

Also, I haven’t given any thought to the performance implications of doing this. Maybe preformace would make this an unworkable solution.

I ended up doing this myself. It works great.

Hi @Dustin_Currie,
I believe this could be accomplished through the use of custom codecs. But using struct tags to describe specific BSON types does seem convenient.

Note, not all BSON types have a single extended JSON keyword: https://github.com/mongodb/specifications/blob/master/source/extended-json.rst#conversion-table. For example: string/bool/document/array/null do not have explicit keywords. $code is used in both the code and codeWithScope BSON types.

I am glad to hear you got this working! If you would like to submit a PR, the Go driver team would be happy to take a look.