Loading...
Searching...
No Matches
BSON Documents

How to create and use BSON documents.

# Create a Document

## From a JSON String

### Basic Example

void example() {
bsoncxx::document::value owner = bsoncxx::from_json(R"(
{
"a": 1,
"b": 2.0,
"c": "three"
}
)");
bsoncxx::document::view doc = owner.view();
EXPECT(doc["a"].get_int32().value == 1);
EXPECT(doc["b"].get_double().value == 2.0);
EXPECT(doc["c"].get_string().value == "three");
}

### With Extended JSON

void example() {
bsoncxx::document::value owner = bsoncxx::from_json(R"(
{
"a": {"$numberInt": "1"},
"b": {"$numberLong": "2"},
"c": {"$numberDouble": "3"}
}
)");
bsoncxx::document::view doc = owner.view();
EXPECT(doc["a"].get_int32().value == 1);
EXPECT(doc["b"].get_int64().value == 2);
EXPECT(doc["c"].get_double().value == 3.0);
}

### With a Sub-Document

void example() {
bsoncxx::document::value doc = bsoncxx::from_json(R"(
{
"v": {"key": "value"}
}
)");
bsoncxx::document::view v = doc["v"].get_document().value;
EXPECT(v == bsoncxx::from_json(R"({"key": "value"})"));
}

### With a Sub-Array

void example() {
bsoncxx::document::value owner = bsoncxx::from_json(R"(
{
"v": [1, 2]
}
)");
bsoncxx::array::view sub = owner.view()["v"].get_array().value;
EXPECT(sub == bsoncxx::builder::basic::make_array(1, 2));
}

### With a User-Defined Literal

void example() {
using namespace bsoncxx;
bsoncxx::document::value a = R"({"key": "value"})"_bson;
bsoncxx::document::value b = bsoncxx::from_json(R"({"key": "value"})");
EXPECT(a == b);
}

## Using the Basic Builder

### Basic Example

void example() {
using bsoncxx::builder::basic::kvp;
bsoncxx::builder::basic::document builder;
builder.append(kvp("a", std::int32_t{1}), kvp("b", 2.0), kvp("c", "three"));
bsoncxx::document::value doc = builder.extract();
EXPECT(doc.view() == bsoncxx::from_json(R"({"a": 1, "b": 2.0, "c": "three"})"));
}

### With make_document

void example() {
using bsoncxx::builder::basic::kvp;
bsoncxx::document::value doc =
bsoncxx::builder::basic::make_document(kvp("a", std::int32_t{1}), kvp("b", 2.0), kvp("c", "three"));
EXPECT(doc.view() == bsoncxx::from_json(R"({"a": 1, "b": 2.0, "c": "three"})"));
}

### With concatenate

// a: {"a": 1}
// b: {"b": 2}
void example(bsoncxx::document::view a, bsoncxx::document::view b) {
bsoncxx::builder::basic::document builder;
builder.append(bsoncxx::builder::concatenate(a));
builder.append(bsoncxx::builder::concatenate(b));
EXPECT(builder.view() == bsoncxx::from_json(R"({"a": 1, "b": 2})"));
}

### With Multiple Appends

void example() {
using bsoncxx::builder::basic::kvp;
bsoncxx::builder::basic::document builder;
builder.append(kvp("a", std::int32_t{1}));
builder.append(kvp("b", 2.0));
builder.append(kvp("c", "three"));
bsoncxx::document::value doc = builder.extract();
EXPECT(doc == bsoncxx::from_json(R"({"a": 1, "b": 2.0, "c": "three"})"));
}

### To Create Multiple Documents

void example() {
using bsoncxx::builder::basic::kvp;
bsoncxx::builder::basic::document builder;
builder.append(kvp("a", 1));
bsoncxx::document::value a = builder.extract();
builder.clear();
builder.append(kvp("b", 2));
bsoncxx::document::value b = builder.extract();
EXPECT(a.view() == bsoncxx::from_json(R"({"a": 1})"));
EXPECT(b.view() == bsoncxx::from_json(R"({"b": 2})"));
}

### With a Value Type

void example() {
using bsoncxx::builder::basic::kvp;
bsoncxx::document::value doc =
bsoncxx::builder::basic::make_document(kvp("a", std::int32_t{1}), kvp("b", 2.0), kvp("c", "three"));
EXPECT(doc == bsoncxx::from_json(R"({"a": 1, "b": 2.0, "c": "three"})"));
}

### With a BSON Type

void example() {
using bsoncxx::builder::basic::kvp;
bsoncxx::types::b_int32 a{1};
bsoncxx::types::b_double b{2.0};
bsoncxx::types::b_string c{"three"};
bsoncxx::document::value doc = bsoncxx::builder::basic::make_document(kvp("a", a), kvp("b", b), kvp("c", c));
EXPECT(doc.view() == bsoncxx::from_json(R"({"a": 1, "b": 2.0, "c": "three"})"));
}

### With a BSON Value

void example() {
using bsoncxx::builder::basic::kvp;
bsoncxx::types::bson_value::value values[]{
std::int32_t{1},
2.0,
"three",
};
bsoncxx::document::value doc =
bsoncxx::builder::basic::make_document(kvp("a", values[0]), kvp("b", values[1]), kvp("c", values[2]));
EXPECT(doc.view() == bsoncxx::from_json(R"({"a": 1, "b": 2.0, "c": "three"})"));
}

### With a Sub-Document

void example() {
using bsoncxx::builder::basic::kvp;
using bsoncxx::builder::basic::make_document;
bsoncxx::document::value subdoc = make_document(kvp("key", "value"));
bsoncxx::document::value owner = make_document(kvp("v", subdoc.view()));
bsoncxx::document::view v = owner.view()["v"].get_document().value;
EXPECT(v == subdoc.view());
}

### With Multiple Sub-Document Appends

void example() {
using bsoncxx::builder::basic::kvp;
std::string keys[] = {"a", "b", "c"};
std::int32_t values[] = {1, 2, 3};
bsoncxx::document::value owner =
bsoncxx::builder::basic::make_document(kvp("v", [&](bsoncxx::builder::basic::sub_document doc) {
for (int i = 0; i < 3; ++i) {
doc.append(kvp(keys[i], values[i]));
}
}));
bsoncxx::document::view v = owner.view()["v"].get_document().value;
EXPECT(v == bsoncxx::from_json(R"({"a": 1, "b": 2, "c": 3})"));
}

### With a Sub-Array

void example() {
using bsoncxx::builder::basic::kvp;
using bsoncxx::builder::basic::make_array;
using bsoncxx::builder::basic::make_document;
bsoncxx::array::value subarr = make_array(1, 2.0, "three");
bsoncxx::document::value owner = make_document(kvp("v", subarr.view()));
bsoncxx::array::view v = owner.view()["v"].get_array().value;
EXPECT(v == subarr.view());
}

### With Multiple Sub-Array Appends

void example() {
using bsoncxx::builder::basic::kvp;
std::int32_t values[] = {1, 2, 3};
bsoncxx::document::value owner =
bsoncxx::builder::basic::make_document(kvp("v", [&](bsoncxx::builder::basic::sub_array arr) {
for (int i = 0; i < 3; ++i) {
arr.append(values[i]);
}
}));
bsoncxx::array::view v = owner.view()["v"].get_array().value;
EXPECT(v == bsoncxx::builder::basic::make_array(1, 2, 3));
}

## From Raw Bytes

### As a View

// {"key": "value"}
void example(std::uint8_t const* data, std::size_t length) {
bsoncxx::document::view doc{data, length};
EXPECT(doc == bsoncxx::from_json(R"({"key": "value"})"));
}

### As a Value

// {"key": "value"}
void example(std::uint8_t const* data, std::size_t length) {
using deleter_type = bsoncxx::document::value::deleter_type;
std::uint8_t* raw = new std::uint8_t[length];
std::copy_n(data, length, raw);
deleter_type deleter = [](std::uint8_t* data) { delete[] data; };
bsoncxx::document::value doc{raw, length, deleter};
EXPECT(doc.view() == bsoncxx::from_json(R"({"key": "value"})"));
}

# Create an Array

## From a JSON String

### Basic Example

void example() {
bsoncxx::document::value owner = bsoncxx::from_json(R"(
[1, 2.0, "three"]
)");
bsoncxx::document::view doc = owner.view();
EXPECT(doc["0"].get_int32().value == 1);
EXPECT(doc["1"].get_double().value == 2.0);
EXPECT(doc["2"].get_string().value == "three");
}

### With Extended JSON

void example() {
bsoncxx::document::value owner = bsoncxx::from_json(R"(
[
{"$numberInt": "1"},
{"$numberLong": "2"},
{"$numberDouble": "3"}
]
)");
bsoncxx::document::view doc = owner.view();
EXPECT(doc["0"].get_int32().value == 1);
EXPECT(doc["1"].get_int64().value == 2);
EXPECT(doc["2"].get_double().value == 3.0);
}

### With a Sub-Document

void example() {
bsoncxx::document::value doc = bsoncxx::from_json(R"(
[
{"key": "value"}
]
)");
bsoncxx::document::view v = doc.view()["0"].get_document().value;
EXPECT(v == bsoncxx::from_json(R"({"key": "value"})"));
}

### With a Sub-Array

void example() {
bsoncxx::document::value doc = bsoncxx::from_json(R"(
[
[1, 2.0, "three"]
]
)");
bsoncxx::array::view sub = doc.view()["0"].get_array().value;
EXPECT(sub == bsoncxx::builder::basic::make_array(1, 2.0, "three"));
}

### With a User-Defined Literal

void example() {
using namespace bsoncxx;
bsoncxx::document::value a = R"([1, 2])"_bson;
bsoncxx::document::value b = bsoncxx::from_json(R"([1, 2])");
EXPECT(a == b);
}

## Using the Basic Builder

### Basic Example

void example() {
bsoncxx::builder::basic::array builder;
builder.append(std::int32_t{1}, 2.0, "three");
bsoncxx::array::value arr = builder.extract();
EXPECT(arr.view() == bsoncxx::builder::basic::make_array(1, 2.0, "three"));
}

### With make_document

void example() {
bsoncxx::array::value owner = bsoncxx::builder::basic::make_array(std::int32_t{1}, 2.0, "three");
bsoncxx::array::view arr = owner.view();
EXPECT(arr[0].get_int32().value == 1);
EXPECT(arr[1].get_double().value == 2.0);
EXPECT(arr[2].get_string().value == "three");
}

### With concatenate

// a: [1]
// b: [2]
void example(bsoncxx::array::view a, bsoncxx::array::view b) {
bsoncxx::builder::basic::array builder;
builder.append(bsoncxx::builder::concatenate(a));
builder.append(bsoncxx::builder::concatenate(b));
EXPECT(builder.view() == bsoncxx::builder::basic::make_array(1, 2));
}

### With Multiple Appends

void example() {
bsoncxx::builder::basic::array builder;
builder.append(std::int32_t{1});
builder.append(2.0);
builder.append("three");
bsoncxx::array::value arr = builder.extract();
EXPECT(arr.view() == bsoncxx::builder::basic::make_array(1, 2.0, "three"));
}

### To Create Multiple Documents

void example() {
bsoncxx::builder::basic::array builder;
builder.append(std::int32_t{1});
bsoncxx::array::value a_owner = builder.extract();
builder.clear();
builder.append(std::int64_t{2});
bsoncxx::array::value b_owner = builder.extract();
bsoncxx::array::view a = a_owner.view();
bsoncxx::array::view b = b_owner.view();
EXPECT(a[0].type() == bsoncxx::type::k_int32);
EXPECT(b[0].type() == bsoncxx::type::k_int64);
EXPECT(a[0].get_int32().value == 1);
EXPECT(b[0].get_int64().value == 2);
}

### With a Value Type

void example() {
bsoncxx::array::value owner = bsoncxx::builder::basic::make_array(std::int32_t{1}, 2.0, "three");
bsoncxx::array::view arr = owner.view();
EXPECT(arr[0].type() == bsoncxx::type::k_int32);
EXPECT(arr[1].type() == bsoncxx::type::k_double);
EXPECT(arr[2].type() == bsoncxx::type::k_string);
EXPECT(arr[0].get_int32().value == 1);
EXPECT(arr[1].get_double().value == 2.0);
EXPECT(arr[2].get_string().value == "three");
}

### With a BSON Type

void example() {
bsoncxx::types::b_int32 a{1};
bsoncxx::types::b_double b{2.0};
bsoncxx::types::b_string c{"three"};
bsoncxx::array::value arr = bsoncxx::builder::basic::make_array(a, b, c);
EXPECT(arr.view() == bsoncxx::builder::basic::make_array(1, 2.0, "three"));
}

### With a BSON Value

void example() {
using bsoncxx::builder::basic::kvp;
bsoncxx::types::bson_value::value values[]{
std::int32_t{1},
2.0,
"three",
};
bsoncxx::array::value arr = bsoncxx::builder::basic::make_array(values[0], values[1], values[2]);
EXPECT(arr.view() == bsoncxx::builder::basic::make_array(1, 2.0, "three"));
}

### With a Sub-Document

void example() {
using bsoncxx::builder::basic::kvp;
using bsoncxx::builder::basic::make_array;
using bsoncxx::builder::basic::make_document;
bsoncxx::document::value subdoc = make_document(kvp("key", "value"));
bsoncxx::array::value owner = make_array(subdoc.view());
bsoncxx::document::view v = owner.view()[0].get_document().value;
EXPECT(v == subdoc.view());
}

### With Multiple Sub-Document Appends

void example() {
using bsoncxx::builder::basic::kvp;
std::string keys[] = {"a", "b", "c"};
std::int32_t values[] = {1, 2, 3};
bsoncxx::array::value owner = bsoncxx::builder::basic::make_array([&](bsoncxx::builder::basic::sub_document doc) {
for (int i = 0; i < 3; ++i) {
doc.append(kvp(keys[i], values[i]));
}
});
bsoncxx::document::view v = owner.view()[0].get_document().value;
EXPECT(v == bsoncxx::from_json(R"({"a": 1, "b": 2, "c": 3})"));
}

### With a Sub-Array

void example() {
using bsoncxx::builder::basic::make_array;
bsoncxx::array::value arr = make_array(1, 2.0, "three");
bsoncxx::array::value owner = make_array(arr.view());
bsoncxx::array::view v = owner.view()[0].get_array().value;
EXPECT(v == arr.view());
}

### With Multiple Sub-Array Appends

void example() {
using bsoncxx::builder::basic::make_array;
std::int32_t values[] = {1, 2, 3};
bsoncxx::array::value owner = make_array([&](bsoncxx::builder::basic::sub_array arr) {
for (int i = 0; i < 3; ++i) {
arr.append(values[i]);
}
});
bsoncxx::array::view v = owner.view()[0].get_array().value;
EXPECT(v == make_array(1, 2, 3));
}

## From Raw Bytes

### As a View

// [1, 2]
void example(std::uint8_t const* data, std::size_t length) {
bsoncxx::array::view arr{data, length};
EXPECT(arr == bsoncxx::builder::basic::make_array(1, 2));
}

### As a Value

// [1, 2]
void example(std::uint8_t const* data, std::size_t length) {
using deleter_type = bsoncxx::array::value::deleter_type;
std::uint8_t* raw = new std::uint8_t[length];
std::copy_n(data, length, raw);
deleter_type deleter = [](std::uint8_t* data) { delete[] data; };
bsoncxx::array::value arr{raw, length, deleter};
EXPECT(arr.view() == bsoncxx::builder::basic::make_array(1, 2));
}

# Access a Document Element

## By Iteration

### Basic Example

// {"a": 1, "b": 2.0, "c": "three"}
void example(bsoncxx::document::view doc) {
for (bsoncxx::document::element e : doc) {
switch (e.type()) {
case bsoncxx::type::k_int32:
EXPECT(e.key() == "a");
EXPECT(e.get_int32().value == 1);
break;
case bsoncxx::type::k_double:
EXPECT(e.key() == "b");
EXPECT(e.get_double().value == 2.0);
break;
case bsoncxx::type::k_string:
EXPECT(e.key() == "c");
EXPECT(e.get_string().value == "three");
break;
}
}
}

### Using Iterators

// {"a": 1, "b": 2}
void example(bsoncxx::document::view doc) {
EXPECT(doc.begin() != doc.end());
auto iter = doc.begin();
EXPECT(iter == doc.begin());
{
bsoncxx::document::element e = *iter;
EXPECT(e.key() == "a");
EXPECT(e.get_int32().value == 1);
}
++iter;
EXPECT(iter->key() == "b");
EXPECT(iter->get_int32().value == 2);
{
auto iter_copy = iter++;
EXPECT(iter_copy != iter);
EXPECT(iter_copy->key() == "b");
EXPECT(iter_copy->get_int32() == 2);
}
EXPECT(iter == doc.end());
}

### Using Algorithms

// {"a": 1, "b": 2.0, "c": "three"}
void example(bsoncxx::document::view doc) {
EXPECT(std::distance(doc.begin(), doc.end()) == 3);
std::vector<bsoncxx::document::element> elements;
std::copy_if(doc.begin(), doc.end(), std::back_inserter(elements), [](bsoncxx::document::element const& e) {
return e.key() == "a" || e.type() == bsoncxx::type::k_string;
});
EXPECT(elements.size() == 2u);
EXPECT(elements[0].key() == "a");
EXPECT(elements[1].key() == "c");
}

## By Key

### Using find()

// {"a": 1, "b": 2}
void example(bsoncxx::document::view doc) {
EXPECT(doc.find("a") == doc.begin());
{
auto iter = doc.find("b");
EXPECT(iter != doc.end());
EXPECT(iter->key() == "b");
EXPECT(iter->get_int32().value == 2);
}
EXPECT(doc.find("x") == doc.end());
}

### Using the Subscript Operator

// {"a": 1, "b": 2}
void example(bsoncxx::document::view doc) {
EXPECT(doc["a"]);
{
bsoncxx::document::element e = doc["b"];
EXPECT(e.key() == "b");
EXPECT(e.get_int32().value == 2);
}
EXPECT(!doc["c"]); // Invalid element.
}

# Access an Array Element

## By Iteration

### Basic Example

// [1, 2.0, "three"]
void example(bsoncxx::array::view arr) {
for (bsoncxx::array::element e : arr) {
switch (e.type()) {
case bsoncxx::type::k_int32:
EXPECT(e.key() == "0");
EXPECT(e.get_int32().value == 1);
break;
case bsoncxx::type::k_double:
EXPECT(e.key() == "1");
EXPECT(e.get_double().value == 2.0);
break;
case bsoncxx::type::k_string:
EXPECT(e.key() == "2");
EXPECT(e.get_string().value == "three");
break;
}
}
}

### Using Iterators

// [1, 2]
void example(bsoncxx::array::view arr) {
EXPECT(arr.begin() != arr.end());
auto iter = arr.begin();
EXPECT(iter == arr.begin());
{
bsoncxx::array::element e = *iter;
EXPECT(e.key() == "0");
EXPECT(e.get_int32().value == 1);
}
++iter;
EXPECT(iter->key() == "1");
EXPECT(iter->get_int32().value == 2);
{
auto iter_copy = iter++;
EXPECT(iter_copy != iter);
EXPECT(iter_copy->key() == "1");
EXPECT(iter_copy->get_int32() == 2);
}
EXPECT(iter == arr.end());
}

### Using Algorithms

// [1, 2.0, "three"]
void example(bsoncxx::array::view arr) {
EXPECT(std::distance(arr.begin(), arr.end()) == 3);
std::vector<bsoncxx::array::element> elements;
std::copy_if(arr.begin(), arr.end(), std::back_inserter(elements), [](bsoncxx::array::element const& e) {
return e.key() == "0" || e.type() == bsoncxx::type::k_string;
});
EXPECT(elements.size() == 2u);
EXPECT(elements[0].key() == "0");
EXPECT(elements[1].key() == "2");
}

## By Key

### Using find()

// [1, 2]
void example(bsoncxx::array::view arr) {
EXPECT(arr.find(0) == arr.begin());
{
auto iter = arr.find(1);
EXPECT(iter != arr.end());
EXPECT(iter->key() == "1");
EXPECT(iter->get_int32().value == 2);
}
EXPECT(arr.find(2) == arr.end());
}

### Using the Subscript Operator

// [1, 2]
void example(bsoncxx::array::view arr) {
EXPECT(arr[0]);
{
bsoncxx::array::element e = arr[1];
EXPECT(e.key() == "1");
EXPECT(e.get_int32().value == 2);
}
EXPECT(!arr[2]); // Invalid element.
}

# Query an Element

## In a Document

### For a Single Type

// {"a": 1, "b": 2.0, "c": "three"}
void example(bsoncxx::document::element e) {
if (e.type() == bsoncxx::type::k_int32) {
EXPECT(e.key() == "a");
bsoncxx::types::b_int32 v = e.get_int32();
EXPECT(v.type_id == bsoncxx::type::k_int32);
EXPECT(v.value == 1);
} else {
EXPECT(e.key() != "a");
}
}

### For Multiple Types

// {"a": 1, "b": 2.0, "c": "three"}
void example(bsoncxx::document::element e) {
switch (e.type()) {
case bsoncxx::type::k_int32: {
EXPECT(e.key() == "a");
bsoncxx::types::b_int32 v = e.get_int32();
EXPECT(v.type_id == bsoncxx::type::k_int32);
EXPECT(v.value == 1);
break;
}
case bsoncxx::type::k_double: {
EXPECT(e.key() == "b");
bsoncxx::types::b_double v = e.get_double();
EXPECT(v.type_id == bsoncxx::type::k_double);
EXPECT(v.value == 2.0);
break;
}
case bsoncxx::type::k_string: {
EXPECT(e.key() == "c");
bsoncxx::types::b_string v = e.get_string();
EXPECT(v.type_id == bsoncxx::type::k_string);
EXPECT(v.value == "three");
break;
}
}
}

## In an Array

### For Single Type

// [1, 2.0, "three"]
void example(bsoncxx::array::element e) {
if (e.type() == bsoncxx::type::k_int32) {
EXPECT(e.key() == "0");
bsoncxx::types::b_int32 v = e.get_int32();
EXPECT(v.type_id == bsoncxx::type::k_int32);
EXPECT(v.value == 1);
} else {
EXPECT(e.key() != "0");
}
}

### For Multiple Types

// [1, 2.0, "three"]
void example(bsoncxx::array::element e) {
switch (e.type()) {
case bsoncxx::type::k_int32: {
EXPECT(e.key() == "0");
bsoncxx::types::b_int32 v = e.get_int32();
EXPECT(v.type_id == bsoncxx::type::k_int32);
EXPECT(v.value == 1);
break;
}
case bsoncxx::type::k_double: {
EXPECT(e.key() == "1");
bsoncxx::types::b_double v = e.get_double();
EXPECT(v.type_id == bsoncxx::type::k_double);
EXPECT(v.value == 2.0);
break;
}
case bsoncxx::type::k_string: {
EXPECT(e.key() == "2");
bsoncxx::types::b_string v = e.get_string();
EXPECT(v.type_id == bsoncxx::type::k_string);
EXPECT(v.value == "three");
break;
}
}
}

## Comparison

### By Type

// {"a": {"$numberInt": "1"}, "b": {"$numberLong": "2"}}
void example(bsoncxx::document::element e) {
std::int32_t a{1};
std::int64_t b{2};
if (e.type() == bsoncxx::type::k_int32) {
EXPECT(e.key() == "a");
EXPECT(e.get_int32().value == a);
} else if (e.type() == bsoncxx::type::k_int64) {
EXPECT(e.key() == "b");
EXPECT(e.get_int64().value == b);
}
}

### By BSON Value

// {"a": {"$numberInt": "1"}, "b": {"$numberLong": "2"}}
void example(bsoncxx::document::element e) {
bsoncxx::types::b_int32 a{1};
bsoncxx::types::b_int64 b{2};
if (e.get_value() == a) {
EXPECT(e.key() == "a");
} else if (e.get_value() == b) {
EXPECT(e.key() == "b");
}
bsoncxx::types::bson_value::view va{a};
bsoncxx::types::bson_value::view vb{b};
if (e == va) {
EXPECT(e.key() == "a");
} else if (e == vb) {
EXPECT(e.key() == "b");
}
}

# Obtain a BSON Value

## From a BSON Type

### As a View

void example() {
using view_type = bsoncxx::types::bson_value::view;
bsoncxx::types::b_int32 v0{1};
bsoncxx::types::b_double v1{2.0};
bsoncxx::types::b_string v2{"three"};
view_type v;
EXPECT(v.type() == bsoncxx::type::k_null);
EXPECT(v.get_null() == bsoncxx::types::b_null{});
v = view_type(v0);
EXPECT(v.type() == v0.type_id);
EXPECT(v.get_int32() == v0);
v = view_type(v1);
EXPECT(v.type() == v1.type_id);
EXPECT(v.get_double() == v1);
v = view_type(v2);
EXPECT(v.type() == v2.type_id);
EXPECT(v.get_string() == v2);
}

### As a Value

void example() {
bsoncxx::types::bson_value::value v = nullptr;
EXPECT(v.view().type() == bsoncxx::type::k_null);
EXPECT(v.view().get_null() == bsoncxx::types::b_null{});
v = bsoncxx::types::b_int32{1};
EXPECT(v.view().type() == bsoncxx::type::k_int32);
EXPECT(v.view().get_int32().value == 1);
v = bsoncxx::types::b_double{2.0};
EXPECT(v.view().type() == bsoncxx::type::k_double);
EXPECT(v.view().get_double().value == 2.0);
v = bsoncxx::types::b_string{"three"};
EXPECT(v.view().type() == bsoncxx::type::k_string);
EXPECT(v.view().get_string().value == "three");
}

## From a Document Element

### As a View

// {"a": 1, "b": 2.0, "c": "three"}
void example(bsoncxx::document::element e) {
bsoncxx::types::bson_value::view v = e.get_value();
EXPECT(v.type() == e.type());
switch (v.type()) {
case bsoncxx::type::k_int32:
EXPECT(e.key() == "a");
EXPECT(v.get_int32() == e.get_int32());
break;
case bsoncxx::type::k_double:
EXPECT(e.key() == "b");
EXPECT(v.get_double() == e.get_double());
break;
case bsoncxx::type::k_string:
EXPECT(e.key() == "c");
EXPECT(v.get_string() == e.get_string());
break;
}
}

### As a Value

void example() {
bsoncxx::types::bson_value::value v = nullptr;
EXPECT(v.view().type() == bsoncxx::type::k_null);
EXPECT(v.view().get_null() == bsoncxx::types::b_null{});
v = bsoncxx::from_json(R"({"v": {"key": "value"}})") // Temporary object.
["v"]
.get_owning_value(); // Copy: no dangling.
EXPECT(v.view().type() == bsoncxx::type::k_document);
v = v.view().get_document().value["key"].get_string(); // Copy: no dangling.
EXPECT(v.view().type() == bsoncxx::type::k_string);
EXPECT(v.view().get_string().value == "value");
}

## From an Array Element

### As a View

// [1, 2.0, "three"]
void example(bsoncxx::array::element e) {
bsoncxx::types::bson_value::view v = e.get_value();
EXPECT(v.type() == e.type());
switch (v.type()) {
case bsoncxx::type::k_int32:
EXPECT(e.key() == "0");
EXPECT(v.get_int32() == e.get_int32());
break;
case bsoncxx::type::k_double:
EXPECT(e.key() == "1");
EXPECT(v.get_double() == e.get_double());
break;
case bsoncxx::type::k_string:
EXPECT(e.key() == "2");
EXPECT(v.get_string() == e.get_string());
break;
}
}

### As a Value

void example() {
bsoncxx::types::bson_value::value v = nullptr;
EXPECT(v.view().type() == bsoncxx::type::k_null);
EXPECT(v.view().get_null() == bsoncxx::types::b_null{});
v = bsoncxx::from_json(R"({"v": ["value"]})") // Temporary object.
["v"]
.get_owning_value(); // Copy: no dangling.
EXPECT(v.view().type() == bsoncxx::type::k_array);
v = v.view().get_array().value[0].get_string(); // Copy: no dangling.
EXPECT(v.view().type() == bsoncxx::type::k_string);
EXPECT(v.view().get_string().value == "value");
}

## From a Value Type

void example() {
bsoncxx::types::bson_value::value v = nullptr;
EXPECT(v.view().type() == bsoncxx::type::k_null);
EXPECT(v.view().get_null() == bsoncxx::types::b_null{});
v = std::int32_t{1};
EXPECT(v.view().type() == bsoncxx::type::k_int32);
EXPECT(v.view().get_int32().value == 1);
v = 2.0;
EXPECT(v.view().type() == bsoncxx::type::k_double);
EXPECT(v.view().get_double().value == 2.0);
v = std::string("three");
EXPECT(v.view().type() == bsoncxx::type::k_string);
EXPECT(v.view().get_string().value == "three");
}

## With make_value

void example() {
using value_type = bsoncxx::types::bson_value::value;
using view_type = bsoncxx::types::bson_value::view;
{
value_type owner = bsoncxx::types::bson_value::make_value(1);
view_type v = owner.view();
EXPECT(v.type() == bsoncxx::type::k_int32);
EXPECT(v.get_int32().value == 1);
}
{
value_type owner = bsoncxx::types::bson_value::make_value(bsoncxx::types::b_int64{2});
view_type v = owner.view();
EXPECT(v.type() == bsoncxx::type::k_int64);
EXPECT(v.get_int64().value == 2);
}
{
value_type owner = bsoncxx::types::bson_value::make_value(std::string("three"));
view_type v = owner.view();
EXPECT(v.type() == bsoncxx::type::k_string);
EXPECT(v.get_string().value == "three");
}
}

# Convert to a JSON String

## From a Document

void example() {
using bsoncxx::ExtendedJsonMode;
using bsoncxx::builder::basic::kvp;
std::uint8_t data[]{"three"}; // Base64: dGhyZWU=
auto data_len = static_cast<std::uint32_t>(sizeof(data) - 1u); // Exclude null terminator.
bsoncxx::types::b_binary binary{bsoncxx::binary_sub_type::k_binary, data_len, data};
bsoncxx::document::value owner = bsoncxx::builder::basic::make_document(
kvp("a", std::int32_t{1}), // "$numberInt": "1"
kvp("b", std::int64_t{2}), // "$numberLong": "2"
kvp("c", binary) // "$binary": { "$base64": "dGhyZWU=", "subType": 00 }
);
bsoncxx::document::view doc = owner.view();
{
// Canonical Extended JSON:
// {
// "a": { "$numberInt": "1" },
// "b": { "$numberLong": "2" },
// "c": {
// "$binary": {
// "base64": "dGhyZWU=",
// "subType": "00"
// }
// }
// }
std::string json = bsoncxx::to_json(doc, ExtendedJsonMode::k_canonical);
EXPECT(
json ==
R"({ "a" : { "$numberInt" : "1" }, "b" : { "$numberLong" : "2" }, "c" : { "$binary" : { "base64" : "dGhyZWU=", "subType" : "00" } } })");
}
{
// Relaxed Extended JSON
// {
// "a": 1,
// "b": 2,
// "c": {
// "$binary": {
// "base64": "dGhyZWU=",
// "subType": "00"
// }
// }
// }
std::string json = bsoncxx::to_json(doc, ExtendedJsonMode::k_relaxed);
EXPECT(json == R"({ "a" : 1, "b" : 2, "c" : { "$binary" : { "base64" : "dGhyZWU=", "subType" : "00" } } })");
}
{
// Legacy Extended JSON
// {
// "a": 1,
// "b": 2,
// "c": {
// "$binary": "dGhyZWU=",
// "$type": "00"
// }
// }
std::string json = bsoncxx::to_json(doc);
EXPECT(json == R"({ "a" : 1, "b" : 2, "c" : { "$binary" : "dGhyZWU=", "$type" : "00" } })");
}
{
std::string a = bsoncxx::to_json(doc);
std::string b = bsoncxx::to_json(doc, ExtendedJsonMode::k_legacy);
EXPECT(a == b);
}
}

## From an Array

void example() {
using bsoncxx::ExtendedJsonMode;
std::uint8_t data[]{"three"}; // Base64: dGhyZWU=
std::uint32_t data_len{5u}; // Exclude null terminator.
bsoncxx::types::b_binary binary{bsoncxx::binary_sub_type::k_binary, data_len, data};
bsoncxx::array::value owner = bsoncxx::builder::basic::make_array(
std::int32_t{1}, // "$numberInt": "1"
std::int64_t{2}, // "$numberLong": "2"
binary // "$binary": { "$base64": "dGhyZWU=", "subType": 00 }
);
bsoncxx::array::view arr = owner.view();
{
// Canonical Extended JSON:
// [
// { "$numberInt": "1" },
// { "$numberLong": "2" },
// {
// "$binary": {
// "base64": "dGhyZWU=",
// "subType": "00"
// }
// }
// ]
std::string json = bsoncxx::to_json(arr, ExtendedJsonMode::k_canonical);
EXPECT(
json ==
R"([ { "$numberInt" : "1" }, { "$numberLong" : "2" }, { "$binary" : { "base64" : "dGhyZWU=", "subType" : "00" } } ])");
}
{
// Relaxed Extended JSON
// [
// 1,
// 2,
// {
// "$binary": {
// "base64": "dGhyZWU=",
// "subType": "00"
// }
// }
// ]
std::string json = bsoncxx::to_json(arr, ExtendedJsonMode::k_relaxed);
EXPECT(json == R"([ 1, 2, { "$binary" : { "base64" : "dGhyZWU=", "subType" : "00" } } ])");
}
{
// Legacy Extended JSON
// [
// 1,
// 2,
// {
// "$binary": "dGhyZWU=",
// "$type": "00"
// }
// ]
std::string json = bsoncxx::to_json(arr);
EXPECT(json == R"([ 1, 2, { "$binary" : "dGhyZWU=", "$type" : "00" } ])");
}
{
std::string a = bsoncxx::to_json(arr);
std::string b = bsoncxx::to_json(arr, ExtendedJsonMode::k_legacy);
EXPECT(a == b);
}
}