...

Source file src/go.mongodb.org/mongo-driver/bson/decoder_example_test.go

Documentation: go.mongodb.org/mongo-driver/bson

     1  // Copyright (C) MongoDB, Inc. 2023-present.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License"); you may
     4  // not use this file except in compliance with the License. You may obtain
     5  // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
     6  
     7  package bson_test
     8  
     9  import (
    10  	"bytes"
    11  	"errors"
    12  	"fmt"
    13  	"io"
    14  
    15  	"go.mongodb.org/mongo-driver/bson"
    16  	"go.mongodb.org/mongo-driver/bson/bsonrw"
    17  )
    18  
    19  func ExampleDecoder() {
    20  	// Marshal a BSON document that contains the name, SKU, and price (in cents)
    21  	// of a product.
    22  	doc := bson.D{
    23  		{Key: "name", Value: "Cereal Rounds"},
    24  		{Key: "sku", Value: "AB12345"},
    25  		{Key: "price_cents", Value: 399},
    26  	}
    27  	data, err := bson.Marshal(doc)
    28  	if err != nil {
    29  		panic(err)
    30  	}
    31  
    32  	// Create a Decoder that reads the marshaled BSON document and use it to
    33  	// unmarshal the document into a Product struct.
    34  	decoder, err := bson.NewDecoder(bsonrw.NewBSONDocumentReader(data))
    35  	if err != nil {
    36  		panic(err)
    37  	}
    38  
    39  	type Product struct {
    40  		Name  string `bson:"name"`
    41  		SKU   string `bson:"sku"`
    42  		Price int64  `bson:"price_cents"`
    43  	}
    44  
    45  	var res Product
    46  	err = decoder.Decode(&res)
    47  	if err != nil {
    48  		panic(err)
    49  	}
    50  
    51  	fmt.Printf("%+v\n", res)
    52  	// Output: {Name:Cereal Rounds SKU:AB12345 Price:399}
    53  }
    54  
    55  func ExampleDecoder_DefaultDocumentM() {
    56  	// Marshal a BSON document that contains a city name and a nested document
    57  	// with various city properties.
    58  	doc := bson.D{
    59  		{Key: "name", Value: "New York"},
    60  		{Key: "properties", Value: bson.D{
    61  			{Key: "state", Value: "NY"},
    62  			{Key: "population", Value: 8_804_190},
    63  			{Key: "elevation", Value: 10},
    64  		}},
    65  	}
    66  	data, err := bson.Marshal(doc)
    67  	if err != nil {
    68  		panic(err)
    69  	}
    70  
    71  	// Create a Decoder that reads the marshaled BSON document and use it to unmarshal the document
    72  	// into a City struct.
    73  	decoder, err := bson.NewDecoder(bsonrw.NewBSONDocumentReader(data))
    74  	if err != nil {
    75  		panic(err)
    76  	}
    77  
    78  	type City struct {
    79  		Name       string      `bson:"name"`
    80  		Properties interface{} `bson:"properties"`
    81  	}
    82  
    83  	// Configure the Decoder to default to decoding BSON documents as the bson.M
    84  	// type if the decode destination has no type information. The Properties
    85  	// field in the City struct will be decoded as a "bson.M" (i.e. map) instead
    86  	// of the default "bson.D".
    87  	decoder.DefaultDocumentM()
    88  
    89  	var res City
    90  	err = decoder.Decode(&res)
    91  	if err != nil {
    92  		panic(err)
    93  	}
    94  
    95  	fmt.Printf("%+v\n", res)
    96  	// Output: {Name:New York Properties:map[elevation:10 population:8804190 state:NY]}
    97  }
    98  
    99  func ExampleDecoder_UseJSONStructTags() {
   100  	// Marshal a BSON document that contains the name, SKU, and price (in cents)
   101  	// of a product.
   102  	doc := bson.D{
   103  		{Key: "name", Value: "Cereal Rounds"},
   104  		{Key: "sku", Value: "AB12345"},
   105  		{Key: "price_cents", Value: 399},
   106  	}
   107  	data, err := bson.Marshal(doc)
   108  	if err != nil {
   109  		panic(err)
   110  	}
   111  
   112  	// Create a Decoder that reads the marshaled BSON document and use it to
   113  	// unmarshal the document into a Product struct.
   114  	decoder, err := bson.NewDecoder(bsonrw.NewBSONDocumentReader(data))
   115  	if err != nil {
   116  		panic(err)
   117  	}
   118  
   119  	type Product struct {
   120  		Name  string `json:"name"`
   121  		SKU   string `json:"sku"`
   122  		Price int64  `json:"price_cents"`
   123  	}
   124  
   125  	// Configure the Decoder to use "json" struct tags when decoding if "bson"
   126  	// struct tags are not present.
   127  	decoder.UseJSONStructTags()
   128  
   129  	var res Product
   130  	err = decoder.Decode(&res)
   131  	if err != nil {
   132  		panic(err)
   133  	}
   134  
   135  	fmt.Printf("%+v\n", res)
   136  	// Output: {Name:Cereal Rounds SKU:AB12345 Price:399}
   137  }
   138  
   139  func ExampleDecoder_extendedJSON() {
   140  	// Define an Extended JSON document that contains the name, SKU, and price
   141  	// (in cents) of a product.
   142  	data := []byte(`{"name":"Cereal Rounds","sku":"AB12345","price_cents":{"$numberLong":"399"}}`)
   143  
   144  	// Create a Decoder that reads the Extended JSON document and use it to
   145  	// unmarshal the document into a Product struct.
   146  	vr, err := bsonrw.NewExtJSONValueReader(bytes.NewReader(data), true)
   147  	if err != nil {
   148  		panic(err)
   149  	}
   150  	decoder, err := bson.NewDecoder(vr)
   151  	if err != nil {
   152  		panic(err)
   153  	}
   154  
   155  	type Product struct {
   156  		Name  string `bson:"name"`
   157  		SKU   string `bson:"sku"`
   158  		Price int64  `bson:"price_cents"`
   159  	}
   160  
   161  	var res Product
   162  	err = decoder.Decode(&res)
   163  	if err != nil {
   164  		panic(err)
   165  	}
   166  
   167  	fmt.Printf("%+v\n", res)
   168  	// Output: {Name:Cereal Rounds SKU:AB12345 Price:399}
   169  }
   170  
   171  func ExampleDecoder_multipleExtendedJSONDocuments() {
   172  	// Define a newline-separated sequence of Extended JSON documents that
   173  	// contain X,Y coordinates.
   174  	data := []byte(`
   175  {"x":{"$numberInt":"0"},"y":{"$numberInt":"0"}}
   176  {"x":{"$numberInt":"1"},"y":{"$numberInt":"1"}}
   177  {"x":{"$numberInt":"2"},"y":{"$numberInt":"2"}}
   178  {"x":{"$numberInt":"3"},"y":{"$numberInt":"3"}}
   179  {"x":{"$numberInt":"4"},"y":{"$numberInt":"4"}}
   180  `)
   181  
   182  	// Create a Decoder that reads the Extended JSON documents and use it to
   183  	// unmarshal the documents Coordinate structs.
   184  	vr, err := bsonrw.NewExtJSONValueReader(bytes.NewReader(data), true)
   185  	if err != nil {
   186  		panic(err)
   187  	}
   188  	decoder, err := bson.NewDecoder(vr)
   189  	if err != nil {
   190  		panic(err)
   191  	}
   192  
   193  	type Coordinate struct {
   194  		X int
   195  		Y int
   196  	}
   197  
   198  	// Read and unmarshal each Extended JSON document from the sequence. If
   199  	// Decode returns error io.EOF, that means the Decoder has reached the end
   200  	// of the input, so break the loop.
   201  	for {
   202  		var res Coordinate
   203  		err = decoder.Decode(&res)
   204  		if errors.Is(err, io.EOF) {
   205  			break
   206  		}
   207  		if err != nil {
   208  			panic(err)
   209  		}
   210  
   211  		fmt.Printf("%+v\n", res)
   212  	}
   213  	// Output:
   214  	// {X:0 Y:0}
   215  	// {X:1 Y:1}
   216  	// {X:2 Y:2}
   217  	// {X:3 Y:3}
   218  	// {X:4 Y:4}
   219  }
   220  

View as plain text