Go slowly   About  Contact  Archives

Get plain JSON from MongoDB in Go

When reading data from MongoDB using Go, we encounter a struct with a JSON generic field that may be an object or an array, which itself may contain nested objects or arrays.

We only need the plain JSON in this case because we already got the parsing code to convert the generic JSON object to specific structs.

To hold unprocessed BSON, we declare our field bson.RawValue:

type object struct {
        Data bson.RawValue `bson:"data"`
}

To parse Data field, we just need to use a trial:

var d interface{}

var m bson.M
var a bson.A

e := object.Data.Unmarshal(&m)
d = m

if e != nil {
        _ = object.Data.Unmarshal(&a)
        d = a
}

This should work, but it results in all bson.M objects becoming Key and Value object like this one:

{
    "Key": "key",
    "Value": "value"
}

instead of this:

{"key": "value"}

This is the behavior of default Mongo decoder registry, so we have to register a new entry for bson.M{}:

rb := bson.NewRegistryBuilder()
rb.RegisterTypeMapEntry(bsontype.EmbeddedDocument, reflect.TypeOf(bson.M{}))

Final working version:

rb := bson.NewRegistryBuilder()
rb.RegisterTypeMapEntry(bsontype.EmbeddedDocument, reflect.TypeOf(bson.M{}))
reg := rb.Build()

var d interface{}

var m bson.M
var a bson.A

e := object.Data.UnmarshalWithRegistry(reg, &m)
d = m

if e != nil {
        _ = object.Data.UnmarshalWithRegistry(reg, &a)
        d = a
}

Written on August 24, 2021.