Overview
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.
Data Types
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 arrayE: 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.
Struct Tags
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 |
|---|---|
| The field will not be marshaled if it is set to the zero value
corresponding to the field type. To globally prevent the driver from
marshaling fields set to a zero value, you can set the |
| If the field is type |
| If the field type is a non-float numeric type, BSON doubles unmarshalled into that field will be truncated at the decimal point. |
| 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:
The driver only marshals and unmarshals exported fields.
The driver generates a BSON key by using the lowercase of the corresponding struct field.
The driver marshals embedded struct fields as subdocuments. Each key is the lowercase of the field's type.
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.
When unmarshalling, the Go driver follows these D/M type mappings for fields of type
any. The driver unmarshals BSON documents unmarshalled into ananyfield as aDtype.
BSON Options
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
BSONOptionsinstance by configuring the following settings:Sets the
UseJSONStructTagsfield totrue, which instructs the driver to use the"json"struct tag if a"bson"struct tag is not specifiedSets the
NilSliceAsEmptyfield totrue, which instructs the driver to marshalnilGo slices as empty BSON arraysSets the
OmitEmptyfield totrue, which instructs the driver to globally omit empty values from the marshaled BSON, rather than set empty values tonull
Passes the
BSONOptionsinstance to theSetBSONOptions()helper method to specify aClientOptionsinstanceCreates a
Clientto apply the specified BSON marshalling and unmarshalling behavior
bsonOpts := &options.BSONOptions { UseJSONStructTags: true, NilSliceAsEmpty: true, OmitEmpty: true, } clientOpts := options.Client(). ApplyURI("<connection string>"). SetBSONOptions(bsonOpts) client, err := mongo.Connect(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.
Unmarshalling
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:
nilif 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 theDecode()method and theDecode()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 bson.Marshal() and
bson.Unmarshal() methods require a parameter that can be encoded into a BSON document,
such as a bson.D type. A Write error occurs if you pass an incorrect type.
For example, if you pass a string to bson.Marshal(), a WriteString error occurs.
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. For more information about how to use the Raw type, see
the Work with Raw BSON Data section.
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.
Work with Raw BSON Data
The Go driver supports working with raw BSON documents through the Raw type. The Raw
type allows you to validate and retrieve elements from a slice of bytes without unmarshalling
the entire BSON document. This is useful in the following situations:
Performing lookups on specific fields without converting the entire document
Reducing memory overhead by avoiding full document unmarshalling
Working directly with binary BSON data received from the database
The Raw type provides methods to validate the BSON document and look up individual
elements by their keys. The following example demonstrates how to validate a raw BSON document and retrieve
a specific field from it:
collection := client.Database("sample_restaurants").Collection("restaurants") findOptions := options.FindOne() var raw bson.Raw err = collection.FindOne( context.TODO(), bson.D{{"name", "Mongo's Pizza"}}, findOptions, ).Decode(&raw) if err != nil { log.Fatalf("Failed to find document: %v", err) } // Print the document type fmt.Printf("Document type: %T\n", raw) // Access a field from the raw document name := raw.Lookup("name").StringValue() fmt.Println("Restaurant name:", name)
Document type: bson.Raw Restaurant name: Mongo's Pizza
To learn more about the Raw family of types, see the Raw BSON API documentation.