Skip to content

Latest commit

 

History

History
303 lines (236 loc) · 8.42 KB

bson.md

File metadata and controls

303 lines (236 loc) · 8.42 KB

bson extension

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.

decode_bson

basic_bson_cursor

encode_bson

basic_bson_encoder

bson_options

Mappings between BSON and jsoncons data items

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

Examples

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)

Document with string and binary

#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)

Decode a BSON 128-bit decimal floating point (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()
{
    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

Encode a BSON 128-bit decimal floating point (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()
{
    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

Regular expression 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()
{
    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

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()
{
    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

See also

byte_string_view

Acknowledgements

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.