bson/bson_encoder_example_test.go

241 lines
6.1 KiB
Go

// Copyright (C) MongoDB, Inc. 2023-present.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
package bson_test
import (
"bytes"
"errors"
"fmt"
"io"
"gitea.psichedelico.com/go/bson"
)
func ExampleEncoder() {
// Create an Encoder that writes BSON values to a bytes.Buffer.
buf := new(bytes.Buffer)
vw := bson.NewDocumentWriter(buf)
encoder := bson.NewEncoder(vw)
type Product struct {
Name string `bson:"name"`
SKU string `bson:"sku"`
Price int64 `bson:"price_cents"`
}
// Use the Encoder to marshal a BSON document that contains the name, SKU,
// and price (in cents) of a product.
product := Product{
Name: "Cereal Rounds",
SKU: "AB12345",
Price: 399,
}
err := encoder.Encode(product)
if err != nil {
panic(err)
}
// Print the BSON document as Extended JSON by converting it to bson.Raw.
fmt.Println(bson.Raw(buf.Bytes()).String())
// Output: {"name": "Cereal Rounds","sku": "AB12345","price_cents": {"$numberLong":"399"}}
}
type CityState struct {
City string
State string
}
func (k CityState) String() string {
return fmt.Sprintf("%s, %s", k.City, k.State)
}
func ExampleEncoder_StringifyMapKeysWithFmt() {
// Create an Encoder that writes BSON values to a bytes.Buffer.
buf := new(bytes.Buffer)
vw := bson.NewDocumentWriter(buf)
encoder := bson.NewEncoder(vw)
// Configure the Encoder to convert Go map keys to BSON document field names
// using fmt.Sprintf instead of the default string conversion logic.
encoder.StringifyMapKeysWithFmt()
// Use the Encoder to marshal a BSON document that contains is a map of
// city and state to a list of zip codes in that city.
zipCodes := map[CityState][]int{
{City: "New York", State: "NY"}: {10001, 10301, 10451},
}
err := encoder.Encode(zipCodes)
if err != nil {
panic(err)
}
// Print the BSON document as Extended JSON by converting it to bson.Raw.
fmt.Println(bson.Raw(buf.Bytes()).String())
// Output: {"New York, NY": [{"$numberInt":"10001"},{"$numberInt":"10301"},{"$numberInt":"10451"}]}
}
func ExampleEncoder_UseJSONStructTags() {
// Create an Encoder that writes BSON values to a bytes.Buffer.
buf := new(bytes.Buffer)
vw := bson.NewDocumentWriter(buf)
encoder := bson.NewEncoder(vw)
type Product struct {
Name string `json:"name"`
SKU string `json:"sku"`
Price int64 `json:"price_cents"`
}
// Configure the Encoder to use "json" struct tags when decoding if "bson"
// struct tags are not present.
encoder.UseJSONStructTags()
// Use the Encoder to marshal a BSON document that contains the name, SKU,
// and price (in cents) of a product.
product := Product{
Name: "Cereal Rounds",
SKU: "AB12345",
Price: 399,
}
err := encoder.Encode(product)
if err != nil {
panic(err)
}
// Print the BSON document as Extended JSON by converting it to bson.Raw.
fmt.Println(bson.Raw(buf.Bytes()).String())
// Output: {"name": "Cereal Rounds","sku": "AB12345","price_cents": {"$numberLong":"399"}}
}
func ExampleEncoder_multipleBSONDocuments() {
// Create an Encoder that writes BSON values to a bytes.Buffer.
buf := new(bytes.Buffer)
vw := bson.NewDocumentWriter(buf)
encoder := bson.NewEncoder(vw)
type Coordinate struct {
X int
Y int
}
// Use the encoder to marshal 5 Coordinate values as a sequence of BSON
// documents.
for i := 0; i < 5; i++ {
err := encoder.Encode(Coordinate{
X: i,
Y: i + 1,
})
if err != nil {
panic(err)
}
}
// Read each marshaled BSON document from the buffer and print them as
// Extended JSON by converting them to bson.Raw.
for {
doc, err := bson.ReadDocument(buf)
if errors.Is(err, io.EOF) {
return
}
if err != nil {
panic(err)
}
fmt.Println(doc.String())
}
// Output:
// {"x": {"$numberInt":"0"},"y": {"$numberInt":"1"}}
// {"x": {"$numberInt":"1"},"y": {"$numberInt":"2"}}
// {"x": {"$numberInt":"2"},"y": {"$numberInt":"3"}}
// {"x": {"$numberInt":"3"},"y": {"$numberInt":"4"}}
// {"x": {"$numberInt":"4"},"y": {"$numberInt":"5"}}
}
func ExampleEncoder_extendedJSON() {
// Create an Encoder that writes canonical Extended JSON values to a
// bytes.Buffer.
buf := new(bytes.Buffer)
vw := bson.NewExtJSONValueWriter(buf, true, false)
encoder := bson.NewEncoder(vw)
type Product struct {
Name string `bson:"name"`
SKU string `bson:"sku"`
Price int64 `bson:"price_cents"`
}
// Use the Encoder to marshal a BSON document that contains the name, SKU,
// and price (in cents) of a product.
product := Product{
Name: "Cereal Rounds",
SKU: "AB12345",
Price: 399,
}
err := encoder.Encode(product)
if err != nil {
panic(err)
}
fmt.Println(buf.String())
// Output: {"name":"Cereal Rounds","sku":"AB12345","price_cents":{"$numberLong":"399"}}
}
func ExampleEncoder_multipleExtendedJSONDocuments() {
// Create an Encoder that writes canonical Extended JSON values to a
// bytes.Buffer.
buf := new(bytes.Buffer)
vw := bson.NewExtJSONValueWriter(buf, true, false)
encoder := bson.NewEncoder(vw)
type Coordinate struct {
X int
Y int
}
// Use the encoder to marshal 5 Coordinate values as a sequence of Extended
// JSON documents.
for i := 0; i < 5; i++ {
err := encoder.Encode(Coordinate{
X: i,
Y: i + 1,
})
if err != nil {
panic(err)
}
}
fmt.Println(buf.String())
// Output:
// {"x":{"$numberInt":"0"},"y":{"$numberInt":"1"}}
// {"x":{"$numberInt":"1"},"y":{"$numberInt":"2"}}
// {"x":{"$numberInt":"2"},"y":{"$numberInt":"3"}}
// {"x":{"$numberInt":"3"},"y":{"$numberInt":"4"}}
// {"x":{"$numberInt":"4"},"y":{"$numberInt":"5"}}
}
func ExampleEncoder_IntMinSize() {
// Create an encoder that will marshal integers as the minimum BSON int size
// (either 32 or 64 bits) that can represent the integer value.
type foo struct {
Bar uint32
}
buf := new(bytes.Buffer)
vw := bson.NewDocumentWriter(buf)
enc := bson.NewEncoder(vw)
enc.IntMinSize()
err := enc.Encode(foo{2})
if err != nil {
panic(err)
}
fmt.Println(bson.Raw(buf.Bytes()).String())
// Output:
// {"bar": {"$numberInt":"2"}}
}