The bson extension implements decode from and encode to the Binary JSON data format. You can either parse into or serialize from a variant-like data structure, basic_json, or your own data structures, using json_type_traits.
BSON data item | jsoncons data item | jsoncons semantic_tag |
---|---|---|
null | null | |
true or false | bool | |
int32 or int64 | int64 | |
int32 or int64 | uint64 | |
UTC datetime | int64 | epoch_milli |
Timestamp | uint64 | |
double | double | |
string | string | |
binary | byte_string | ext |
array | array | |
embedded document | object | |
decimal128 (since 0.165.0) | string | float128 |
ObjectId (since 0.165.0) | string | id |
regex (since 0.165.0) | string | regex |
JavaScript code (since 0.165.0) | string | code |
min_key (since 0.165.0) | string | |
max_key (since 0.165.0) | string | |
undefined (since 0.165.0) | null | undefined |
symbol (since 0.165.0) | string |
Document with string and binary
Decode a BSON 128-bit decimal floating point (since 0.165.0)
Encode a BSON 128-bit decimal floating point (since 0.165.0)
Regular expression data (since 0.165.0)
ObjectId data (since 0.165.0)
#include <jsoncons/json.hpp>
#include <jsoncons_ext/bson/bson.hpp>
#include <cassert>
using jsoncons::json;
namespace bson = jsoncons::bson; // for brevity
int main()
{
// Create some bson
std::vector<uint8_t> buffer;
bson::bson_bytes_encoder encoder(buffer);
encoder.begin_object(); // The total number of bytes comprising
// the bson document will be calculated
encoder.key("Hello");
encoder.string_value("World");
encoder.key("Data");
std::vector<uint8_t> bstr = {'f','o','o','b','a','r'};
encoder.byte_string_value(bstr); // default subtype is user defined
// or encoder.byte_string_value(bstr, 0x80);
encoder.end_object();
encoder.flush();
std::cout << "(1)\n" << jsoncons::byte_string_view(buffer) << "\n";
/*
0x27,0x00,0x00,0x00, // Total number of bytes comprising the document (40 bytes)
0x02, // URF-8 string
0x48,0x65,0x6c,0x6c,0x6f, // Hello
0x00, // trailing byte
0x06,0x00,0x00,0x00, // Number bytes in string (including trailing byte)
0x57,0x6f,0x72,0x6c,0x64, // World
0x00, // trailing byte
0x05, // binary
0x44,0x61,0x74,0x61, // Data
0x00, // trailing byte
0x06,0x00,0x00,0x00, // number of bytes
0x80, // subtype
0x66,0x6f,0x6f,0x62,0x61,0x72,
0x00
*/
ojson j = bson::decode_bson<ojson>(buffer);
std::cout << "(2)\n" << pretty_print(j) << "\n\n";
std::cout << "(3) " << j["Data"].tag() << "(" << j["Data"].ext_tag() << ")\n\n";
// Get binary value as a std::vector<uint8_t>
auto bstr2 = j["Data"].as<std::vector<uint8_t>>();
assert(bstr2 == bstr);
std::vector<uint8_t> buffer2;
bson::encode_bson(j, buffer2);
assert(buffer2 == buffer);
}
Output:
(1)
27,00,00,00,02,48,65,6c,6c,6f,00,06,00,00,00,57,6f,72,6c,64,00,05,44,61,74,61,00,06,00,00,00,80,66,6f,6f,62,61,72,00
(2)
{
"Hello": "World",
"Data": "Zm9vYmFy"
}
(3) ext(128)
#include <jsoncons/json.hpp>
#include <jsoncons_ext/bson/bson.hpp>
#include <cassert>
using jsoncons::json;
namespace bson = jsoncons::bson; // for brevity
int main()
{
std::vector<uint8_t> input = {
0x18,0x00,0x00,0x00, // Document has 24 bytes
0x13, // 128-bit decimal floating point
0x61,0x00, // "a"
0x01,0x00,0x00,0x00,
0x00,0x00,0x00,0x00, // 1E-6176
0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,
0x00 // terminating null
};
json j = bson::decode_bson<json>(input);
std::cout << "(1) " << j << "\n\n";
std::cout << "(2) " << j.at("a").tag() << "\n\n";
std::vector<char> output;
bson::encode_bson(j, output);
assert(output == input);
}
Output:
(1) {"a":"1E-6176"}
(2) float128
#include <jsoncons/json.hpp>
#include <jsoncons_ext/bson/bson.hpp>
#include <cassert>
using jsoncons::json;
namespace bson = jsoncons::bson; // for brevity
int main()
{
json j;
j.try_emplace("a", "1E-6176", jsoncons::semantic_tag::float128);
// or j["a"] = json("1E-6176", jsoncons::semantic_tag::float128);
std::cout << "(1) " << j << "\n\n";
std::cout << "(2) " << j.at("a").tag() << "\n\n";
std::vector<char> output;
bson::encode_bson(j, output);
std::cout << "(3) " << jsoncons::byte_string_view(output) << "\n\n";
/*
18,00,00,00, // document has 24 bytes
13, // 128-bit decimal floating point
13,00, // "a"
01,00,00,00,
00,00,00,00, // 1E-6176
00,00,00,00,
00,00,00,00,
00 // terminating null
*/
}
Output:
(1) {"a":"1E-6176"}
(2) float128
(3) 18,00,00,00,13,61,00,01,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
#include <jsoncons/json.hpp>
#include <jsoncons_ext/bson/bson.hpp>
#include <cassert>
using jsoncons::json;
namespace bson = jsoncons::bson; // for brevity
int main()
{
std::vector<uint8_t> input = {
0x16,0x00,0x00,0x00, // Document has 22 bytes
0x0B, // Regular expression
0x72,0x65,0x67,0x65,0x78,0x00, // "regex"
0x5E,0x61,0x62,0x63,0x64,0x00, // "^abcd"
0x69,0x6C,0x78,0x00, // "ilx"
0x00 // terminating null
};
json j = bson::decode_bson<json>(input);
std::cout << "(1) " << j << "\n\n";
std::cout << "(2) " << j.at("regex").tag() << "\n\n";
std::vector<char> output;
bson::encode_bson(j, output);
assert(output == input);
}
Output:
(1) {"regex":"/^abcd/ilx"}
(2) regex
#include <jsoncons/json.hpp>
#include <jsoncons_ext/bson/bson.hpp>
#include <cassert>
using jsoncons::json;
namespace bson = jsoncons::bson; // for brevity
int main()
{
std::vector<uint8_t> input = {
0x16,0x00,0x00,0x00, // Document has 22 bytes
0x07, // ObjectId
0x6F,0x69,0x64,0x00, // "oid"
0x12,0x34,0x56,0x78,0x90,0xAB,
0xCD,0xEF,0x12,0x34,0xAB,0xCD, // (byte*12)
0x00 // terminating null
};
json j = bson::decode_bson<json>(input);
std::cout << "(1) " << j << "\n\n";
std::cout << "(2) " << j.at("oid").tag() << "\n\n";
std::vector<char> output;
bson::encode_bson(j, output);
assert(output == input);
}
Output:
(1) {"oid":"1234567890abcdef1234abcd"}
(2) id
The jsoncons implementations of BSON decimal128 to and from string, and ObjectId to and from string, are based on the Apache 2 licensed libbson.
The decimal128, regex, and ObjectId examples are from the libbson test cases.