MongoDB C++ Driver mongocxx-3.11.0
Loading...
Searching...
No Matches
BSON Documents

Table of Contents

How to create and use BSON documents.

Create a Document

From a JSON String

Basic Example

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

With Extended JSON

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

With a Sub-Document

void example() {
{
"v": {"key": "value"}
}
)");
bsoncxx::document::view v = doc["v"].get_document().value;
ASSERT(v["key"].get_string().value.compare("value") == 0);
}

With a Sub-Array

void example() {
{
"v": [1, 2]
}
)");
bsoncxx::array::view sub = owner.view()["v"].get_array().value;
ASSERT(sub[0].get_int32().value == 1);
ASSERT(sub[1].get_int32().value == 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"})");
ASSERT(a == b);
}

Using the Basic Builder

Basic Example

void example() {
builder.append(kvp("a", std::int32_t{1}), kvp("b", 2.0), kvp("c", "three"));
bsoncxx::document::value owner = builder.extract();
bsoncxx::document::view doc = owner.view();
ASSERT(doc["a"].get_int32().value == 1);
ASSERT(doc["b"].get_double().value == 2.0);
ASSERT(doc["c"].get_string().value.compare("three") == 0);
}

With make_document

void example() {
kvp("a", std::int32_t{1}), kvp("b", 2.0), kvp("c", "three"));
bsoncxx::document::view doc = owner.view();
ASSERT(doc["a"].get_int32().value == 1);
ASSERT(doc["b"].get_double().value == 2.0);
ASSERT(doc["c"].get_string().value.compare("three") == 0);
}

With Multiple Appends

void example() {
builder.append(kvp("a", std::int32_t{1}));
builder.append(kvp("b", 2.0));
builder.append(kvp("c", "three"));
bsoncxx::document::value owner = builder.extract();
bsoncxx::document::view doc = owner.view();
ASSERT(doc["a"].get_int32().value == 1);
ASSERT(doc["b"].get_double().value == 2.0);
ASSERT(doc["c"].get_string().value.compare("three") == 0);
}

To Create Multiple Documents

void example() {
builder.append(kvp("v", std::int32_t{1}));
bsoncxx::document::value a_owner = builder.extract();
builder.clear();
builder.append(kvp("v", std::int64_t{2}));
bsoncxx::document::value b_owner = builder.extract();
bsoncxx::document::view a = a_owner.view();
bsoncxx::document::view b = b_owner.view();
ASSERT(a["v"].type() == bsoncxx::type::k_int32);
ASSERT(b["v"].type() == bsoncxx::type::k_int64);
ASSERT(a["v"].get_int32().value == 1);
ASSERT(b["v"].get_int64().value == 2);
}

With a Value Type

void example() {
kvp("a", std::int32_t{1}), kvp("b", 2.0), kvp("c", "three"));
bsoncxx::document::view doc = owner.view();
ASSERT(doc["a"].type() == bsoncxx::type::k_int32);
ASSERT(doc["b"].type() == bsoncxx::type::k_double);
ASSERT(doc["c"].type() == bsoncxx::type::k_string);
ASSERT(doc["a"].get_int32().value == 1);
ASSERT(doc["b"].get_double().value == 2.0);
ASSERT(doc["c"].get_string().value.compare("three") == 0);
}

With a BSON Type

void example() {
bsoncxx::builder::basic::make_document(kvp("a", a), kvp("b", b), kvp("c", c));
bsoncxx::document::view doc = owner.view();
ASSERT(doc["a"].type() == bsoncxx::type::k_int32);
ASSERT(doc["b"].type() == bsoncxx::type::k_double);
ASSERT(doc["c"].type() == bsoncxx::type::k_string);
ASSERT(doc["a"].get_int32() == a);
ASSERT(doc["b"].get_double() == b);
ASSERT(doc["c"].get_string() == c);
}

With a BSON Value

void example() {
std::int32_t{1},
2.0,
"three",
};
kvp("a", values[0]), kvp("b", values[1]), kvp("c", values[2]));
bsoncxx::document::view doc = owner.view();
ASSERT(doc["a"].type() == bsoncxx::type::k_int32);
ASSERT(doc["b"].type() == bsoncxx::type::k_double);
ASSERT(doc["c"].type() == bsoncxx::type::k_string);
ASSERT(doc["a"].get_value() == values[0]);
ASSERT(doc["b"].get_value() == values[1]);
ASSERT(doc["c"].get_value() == values[2]);
}

With a Sub-Document

void example() {
bsoncxx::document::value owner = make_document(kvp("v", make_document(kvp("key", "value"))));
bsoncxx::document::view v = owner.view()["v"].get_document().value;
ASSERT(v["key"].get_string().value.compare("value") == 0);
}

With Multiple Sub-Document Appends

void example() {
std::string keys[] = {"a", "b", "c"};
std::int32_t values[] = {1, 2, 3};
for (int i = 0; i < 3; ++i) {
doc.append(kvp(keys[i], values[i]));
}
}));
bsoncxx::document::view v = owner.view()["v"].get_document().value;
ASSERT(v["a"].get_int32().value == 1);
ASSERT(v["b"].get_int32().value == 2);
ASSERT(v["c"].get_int32().value == 3);
}

With a Sub-Array

void example() {
make_document(kvp("v", make_array(std::int32_t{1}, std::int64_t{2})));
bsoncxx::array::view v = owner.view()["v"].get_array().value;
ASSERT(v[0].type() == bsoncxx::type::k_int32);
ASSERT(v[1].type() == bsoncxx::type::k_int64);
ASSERT(v[0].get_int32().value == 1);
ASSERT(v[1].get_int64().value == 2);
}

With Multiple Sub-Array Appends

void example() {
std::int32_t values[] = {1, 2, 3};
for (int i = 0; i < 3; ++i) {
arr.append(values[i]);
}
}));
bsoncxx::array::view v = owner.view()["v"].get_array().value;
ASSERT(v[0].get_int32().value == 1);
ASSERT(v[1].get_int32().value == 2);
ASSERT(v[2].get_int32().value == 3);
}

From Raw Bytes

As a View

// {"key": "value"}
void example(const std::uint8_t* data, std::size_t length) {
bsoncxx::document::view doc{data, length};
ASSERT(doc["key"].get_string().value.compare("value") == 0);
}

As a Value

// {"key": "value"}
void example(const std::uint8_t* 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 owner{raw, length, deleter};
bsoncxx::document::view doc = owner.view();
ASSERT(doc["key"].get_string().value.compare("value") == 0);
}

Create an Array

From a JSON String

Basic Example

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

With Extended JSON

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

With a Sub-Document

void example() {
[
{"key": "value"}
]
)");
bsoncxx::document::view v = owner.view()["0"].get_document().value;
ASSERT(v["key"].get_string().value.compare("value") == 0);
}

With a Sub-Array

void example() {
[
[1, 2]
]
)");
bsoncxx::array::view sub = owner.view()["0"].get_array().value;
ASSERT(sub[0].get_int32().value == 1);
ASSERT(sub[1].get_int32().value == 2);
}

With a User-Defined Literal

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

Using the Basic Builder

Basic Example

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

With make_document

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

With Multiple Appends

void example() {
builder.append(std::int32_t{1});
builder.append(2.0);
builder.append("three");
bsoncxx::array::value owner = builder.extract();
bsoncxx::array::view arr = owner.view();
ASSERT(arr[0].get_int32().value == 1);
ASSERT(arr[1].get_double().value == 2.0);
ASSERT(arr[2].get_string().value.compare("three") == 0);
}

To Create Multiple Documents

void example() {
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();
ASSERT(a[0].type() == bsoncxx::type::k_int32);
ASSERT(b[0].type() == bsoncxx::type::k_int64);
ASSERT(a[0].get_int32().value == 1);
ASSERT(b[0].get_int64().value == 2);
}

With a Value Type

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

With a BSON Type

void example() {
bsoncxx::array::view arr = owner.view();
ASSERT(arr[0].type() == bsoncxx::type::k_int32);
ASSERT(arr[1].type() == bsoncxx::type::k_double);
ASSERT(arr[2].type() == bsoncxx::type::k_string);
ASSERT(arr[0].get_int32().value == 1);
ASSERT(arr[1].get_double().value == 2.0);
ASSERT(arr[2].get_string().value.compare("three") == 0);
}

With a BSON Value

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

With a Sub-Document

void example() {
bsoncxx::document::view v = owner.view()[0].get_document().value;
ASSERT(v["key"].get_string().value.compare("value") == 0);
}

With Multiple Sub-Document Appends

void example() {
std::string keys[] = {"a", "b", "c"};
std::int32_t values[] = {1, 2, 3};
for (int i = 0; i < 3; ++i) {
doc.append(kvp(keys[i], values[i]));
}
});
bsoncxx::document::view v = owner.view()[0].get_document().value;
ASSERT(v["a"].get_int32().value == 1);
ASSERT(v["b"].get_int32().value == 2);
ASSERT(v["c"].get_int32().value == 3);
}

With a Sub-Array

void example() {
bsoncxx::array::value owner = make_array(make_array(std::int32_t{1}, std::int64_t{2}));
bsoncxx::array::view v = owner.view()[0].get_array().value;
ASSERT(v[0].type() == bsoncxx::type::k_int32);
ASSERT(v[1].type() == bsoncxx::type::k_int64);
ASSERT(v[0].get_int32().value == 1);
ASSERT(v[1].get_int64().value == 2);
}

With Multiple Sub-Array Appends

void example() {
std::int32_t values[] = {1, 2, 3};
for (int i = 0; i < 3; ++i) {
arr.append(values[i]);
}
});
bsoncxx::array::view v = owner.view()[0].get_array().value;
ASSERT(v[0].get_int32().value == 1);
ASSERT(v[1].get_int32().value == 2);
ASSERT(v[2].get_int32().value == 3);
}

From Raw Bytes

As a View

// [1, 2]
void example(const std::uint8_t* data, std::size_t length) {
bsoncxx::array::view arr{data, length};
ASSERT(arr[0].get_int32().value == 1);
ASSERT(arr[1].get_int32().value == 2);
}

As a Value

// [1, 2]
void example(const std::uint8_t* 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 owner{raw, length, deleter};
bsoncxx::array::view arr = owner.view();
ASSERT(arr[0].get_int32().value == 1);
ASSERT(arr[1].get_int32().value == 2);
}

Access a Document Element

By Iteration

Basic Example

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

Using Iterators

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

Using Algorithms

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

By Key

Using find()

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

Using the Subscript Operator

// {"a": 1, "b": 2}
void example(bsoncxx::document::view doc) {
ASSERT(doc["a"]);
{
ASSERT(e.key().compare("b") == 0);
ASSERT(e.get_int32().value == 2);
}
ASSERT(!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:
ASSERT(e.key().compare("0") == 0);
ASSERT(e.get_int32().value == 1);
break;
case bsoncxx::type::k_double:
ASSERT(e.key().compare("1") == 0);
ASSERT(e.get_double().value == 2.0);
break;
case bsoncxx::type::k_string:
ASSERT(e.key().compare("2") == 0);
ASSERT(e.get_string().value.compare("three") == 0);
break;
}
}
}

Using Iterators

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

Using Algorithms

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

By Key

Using find()

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

Using the Subscript Operator

// [1, 2]
void example(bsoncxx::array::view arr) {
ASSERT(arr[0]);
{
ASSERT(e.key().compare("1") == 0);
ASSERT(e.get_int32().value == 2);
}
ASSERT(!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) {
ASSERT(e.key().compare("a") == 0);
bsoncxx::types::b_int32 v = e.get_int32();
ASSERT(v.type_id == bsoncxx::type::k_int32);
ASSERT(v.value == 1);
} else {
ASSERT(e.key().compare("a") != 0);
}
}

For Multiple Types

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

In an Array

For Single Type

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

For Multiple Types

// [1, 2.0, "three"]
void example(bsoncxx::array::element e) {
switch (e.type()) {
case bsoncxx::type::k_int32: {
ASSERT(e.key().compare("0") == 0);
bsoncxx::types::b_int32 v = e.get_int32();
ASSERT(v.type_id == bsoncxx::type::k_int32);
ASSERT(v.value == 1);
break;
}
case bsoncxx::type::k_double: {
ASSERT(e.key().compare("1") == 0);
bsoncxx::types::b_double v = e.get_double();
ASSERT(v.type_id == bsoncxx::type::k_double);
ASSERT(v.value == 2.0);
break;
}
case bsoncxx::type::k_string: {
ASSERT(e.key().compare("2") == 0);
bsoncxx::types::b_string v = e.get_string();
ASSERT(v.type_id == bsoncxx::type::k_string);
ASSERT(v.value.compare("three") == 0);
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) {
ASSERT(e.key().compare("a") == 0);
ASSERT(e.get_int32().value == a);
} else if (e.type() == bsoncxx::type::k_int64) {
ASSERT(e.key().compare("b") == 0);
ASSERT(e.get_int64().value == b);
}
}

By BSON Value

// {"a": {"$numberInt": "1"}, "b": {"$numberLong": "2"}}
void example(bsoncxx::document::element e) {
if (e.get_value() == a) {
ASSERT(e.key().compare("a") == 0);
} else if (e.get_value() == b) {
ASSERT(e.key().compare("b") == 0);
}
if (e == va) {
ASSERT(e.key().compare("a") == 0);
} else if (e == vb) {
ASSERT(e.key().compare("b") == 0);
}
}

Obtain a BSON Value

From a BSON Type

As a View

void example() {
view_type v;
ASSERT(v.type() == bsoncxx::type::k_null);
ASSERT(v.get_null() == bsoncxx::types::b_null{});
v = view_type(v0);
ASSERT(v.type() == v0.type_id);
ASSERT(v.get_int32() == v0);
v = view_type(v1);
ASSERT(v.type() == v1.type_id);
ASSERT(v.get_double() == v1);
v = view_type(v2);
ASSERT(v.type() == v2.type_id);
ASSERT(v.get_string() == v2);
}

As a Value

void example() {
ASSERT(v.view().type() == bsoncxx::type::k_null);
ASSERT(v.view().get_null() == bsoncxx::types::b_null{});
ASSERT(v.view().type() == bsoncxx::type::k_int32);
ASSERT(v.view().get_int32().value == 1);
ASSERT(v.view().type() == bsoncxx::type::k_double);
ASSERT(v.view().get_double().value == 2.0);
ASSERT(v.view().type() == bsoncxx::type::k_string);
ASSERT(v.view().get_string().value.compare("three") == 0);
}

From a Document Element

As a View

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

As a Value

void example() {
ASSERT(v.view().type() == bsoncxx::type::k_null);
ASSERT(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.
ASSERT(v.view().type() == bsoncxx::type::k_document);
v = v.view().get_document().value["key"].get_string(); // Copy: no dangling.
ASSERT(v.view().type() == bsoncxx::type::k_string);
ASSERT(v.view().get_string().value.compare("value") == 0);
}

From an Array Element

As a View

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

As a Value

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

From a Value Type

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

With make_value

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

Convert to a JSON String

From a Document

void example() {
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};
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);
ASSERT(
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);
ASSERT(
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);
ASSERT(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);
ASSERT(a == b);
}
}

From an Array

void example() {
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};
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);
ASSERT(
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);
ASSERT(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);
ASSERT(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);
ASSERT(a == b);
}
}