Docs Menu
Docs Home
/ / /
Go Driver
/

Work with BSON

On this page

  • Overview
  • Data Types
  • Struct Tags
  • BSON Options
  • Unmarshalling

In this guide, you can learn about how the Go driver handles conversions between BSON and Go types. The process of converting a Go type to BSON is called marshalling, while the reverse process is called unmarshalling.

The following sections explain how the Go driver represents BSON data and how you can adjust default marshalling and unmarshalling behaviors.

MongoDB stores documents in a binary representation called BSON that allows for easy and flexible data processing.

The Go driver provides four main types for working with BSON data:

  • D: An ordered representation of a BSON document (slice)

  • M: An unordered representation of a BSON document (map)

  • A: An ordered representation of a BSON array

  • E: A single element inside a D type

The following example demonstrates how to construct a query filter by using the bson.D type to match documents in which the quantity field value is greater than 100:

filter := bson.D{{"quantity", bson.D{{"$gt", 100}}}}

To learn more about how the Go driver handles BSON data, see the bson package API documentation.

In Go, a struct is a collection of data fields with declared data types. You can modify the default marshalling and unmarshalling behavior of a struct field by using struct tags, which are optional pieces of metadata attached to struct fields. The most common use of struct tags is for specifying the field name in the BSON document that corresponds to the struct field. The following table describes the additional struct tags that you can use in the Go driver:

Struct Tag
Description
omitempty
The field will not be marshalled if it is set to the zero value corresponding to the field type.
minsize
If the field is type int64, uint, uint32, or uint64 and the value of the field can fit in a signed int32, the field will be serialized as a BSON int32 rather than a BSON int64. If the value can't fit in a signed int32, this tag is ignored.
truncate
If the field type is a non-float numeric type, BSON doubles unmarshalled into that field will be truncated at the decimal point.
inline
If the field type is a struct or map field, the field will be flattened when marshalling and unflattened when unmarshalling.

If you don't specify struct tags, the Go driver marshals structs by using the following rules:

  1. The driver only marshals and unmarshals exported fields.

  2. The driver generates a BSON key by using the lowercase of the corresponding struct field.

  3. The driver marshals embedded struct fields as subdocuments. Each key is the lowercase of the field's type.

  4. The driver marshals a pointer field as the underlying type if the pointer is non-nil. If the pointer is nil, the driver marshals it as a BSON null value.

  5. When unmarshalling, the Go driver follows these D/M type mappings for fields of type interface{}. The driver unmarshals BSON documents unmarshalled into an interface{} field as a D type.

The following example demonstrates how the Go driver marshals a struct with various struct tags:

type Address struct {
Street string
City string
State string
}
type Student struct {
FirstName string `bson:"first_name,omitempty"`
LastName string `bson:"last_name,omitempty"`
Address Address `bson:"inline"`
Age int
}
coll := client.Database("db").Collection("students")
address1 := Address{ "1 Lakewood Way", "Elwood City", "PA" }
student1 := Student{ FirstName : "Arthur", Address : address1, Age : 8}
_, err = coll.InsertOne(context.TODO(), student1)

The corresponding BSON representation looks like this:

{
"_id" : ObjectId("..."),
"first_name" : "Arthur",
"street" : "1 Lakewood Way",
"city" : "Elwood City",
"state" : "PA",
"age" : 8
}

In this example, struct tags make the driver:

  • Set custom BSON field names such as first_name

  • Omit the empty LastName field

  • Flatten the nested struct and bring all fields up to the top level

The following example demonstrates how the Go driver marshals a struct without any struct tags:

type Address struct {
Street string
City string
State string
}
type Student struct {
FirstName string
LastName string
Address Address
Age int
}
coll := client.Database("db").Collection("students")
address1 := Address{ "1 Lakewood Way", "Elwood City", "PA" }
student1 := Student{ FirstName : "Arthur", Address : address1, Age : 8}
_, err = coll.InsertOne(context.TODO(), student1)

The corresponding BSON representation looks like this:

{
"_id" : ObjectId("..."),
"firstname" : "Arthur",
"lastname" : "",
"address": {
"street" : "1 Lakewood Way",
"city" : "Elwood City",
"state" : "PA"
},
"age" : 8
}

Without struct tags, the driver:

  • Sets the lowercase of the struct fields as the BSON field names

  • Includes an empty lastname field

  • Stores the Address field as a nested value

You can specify BSON options to adjust the marshalling and unmarshalling behavior of your Client instance. To set BSON options on your Client, create and configure a BSONOptions instance.

This example performs the following actions:

  • Creates a BSONOptions instance by configuring the following settings:

    • Sets the UseJSONStructTags field to true, which instructs the driver to use the "json" struct tag if a "bson" struct tag is not specified

    • Sets the NilSliceAsEmpty field to true, which instructs the driver to marshal nil Go slices as empty BSON arrays

  • Passes the BSONOptions instance to the SetBSONOptions() helper method to specify a ClientOptions instance

  • Creates a Client to apply the specified BSON marshalling and unmarshalling behavior

bsonOpts := &options.BSONOptions {
UseJSONStructTags: true,
NilSliceAsEmpty: true,
}
clientOpts := options.Client().
ApplyURI("<connection string>").
SetBSONOptions(bsonOpts)
client, err := mongo.Connect(context.TODO(), clientOpts)

Tip

To learn more about the BSONOptions type, see the BSONOptions API documentation. For an example that specifies a BSONOptions instance and creates a client with these options, see the Connect() BSONOptions example.

You can unmarshal BSON documents by using the Decode() method on the result of the FindOne method or any *mongo.Cursor instance.

The Decode() method returns an error type which contains one of the following values:

  • nil if a document matched your query, and there were no errors retrieving and unmarshalling the document.

  • If the driver retrieved your document but could not unmarshal your result, the Decode() method returns the unmarshalling error.

  • If there was an error retrieving your document during execution of the FindOne() method, the error propagates to the Decode() method and the Decode() method returns the error.

When used on the SingleResult type returned by the FindOne() method, Decode() can also return the ErrNoDocuments error if no documents matched the query filter.

The following example demonstrates how you can use the Decode() method to unmarshal and read the result of a simple FindOne() operation:

coll := client.Database("db").Collection("students")
filter := bson.D{{"age", 8}}
var result bson.D
err := coll.FindOne(context.TODO(), filter).Decode(&result)
fmt.Println(result)
[{_id ObjectID("...")} {first_name Arthur} {street 1 Fern Way} {city Elwood City} {state PA} {age 8}]

The Cursor type also uses the All() method, which unmarshals all documents stored in the cursor into an array at the same time.

The bson package includes a family of Marshal() and Unmarshal() methods that work with BSON-encoded data of []byte type.

The following code demonstrates how you can unmarshal BSON back into a user-defined struct by using methods from the bson package:

type Item struct {
Category string
Quantity int32
}
doc, err := bson.Marshal(bson.D{{"category", "plate"}, {"quantity", 6}})
var test Item
err = bson.Unmarshal(doc, &test)
fmt.Printf("Unmarshalled Struct:\n%+v\n", test)
Unmarshalled Struct:
{Category:plate Quantity:6}

Note

You can use the Raw type to retrieve elements from a BSON document byte slice without unmarshalling it to a Go type. This type allows you to look up individual elements without unmarshalling the entire BSON document.

To learn more about the marshalling and unmarshalling methods used with the Cursor type, see the Cursor API documentation

To learn more about the marshalling and unmarshalling methods in the bson package, see the bson API documentation

Back

Enterprise Authentication