1BSON_TUTORIAL(3)                    libbson                   BSON_TUTORIAL(3)
2
3
4

NAME

6       bson_tutorial - Tutorial
7

USING LIBBSON IN YOUR C PROGRAM

9   Include bson.h
10       All  libbson's  functions  and  types are available in one header file.
11       Simply include bson.h:
12
13       hello_bson.c
14
15          #include <stdio.h>
16          #include <bson/bson.h>
17
18          int
19          main (int argc, const char **argv)
20          {
21             bson_t *b;
22             char *j;
23
24             b = BCON_NEW ("hello", BCON_UTF8 ("bson!"));
25             j = bson_as_canonical_extended_json (b, NULL);
26             printf ("%s\n", j);
27
28             bson_free (j);
29             bson_destroy (b);
30
31             return 0;
32          }
33
34
35   CMake
36       The libbson installation includes a CMake config-file package,  so  you
37       can  use  CMake's find_package command to import libbson's CMake target
38       and link to libbson (as a shared library):
39
40       CMakeLists.txt
41
42          # Specify the minimum version you require.
43          find_package (bson-1.0 1.7 REQUIRED)
44
45          # The "hello_bson.c" sample program is shared among four tests.
46          add_executable (hello_bson ../../hello_bson.c)
47          target_link_libraries (hello_bson PRIVATE mongo::bson_shared)
48
49
50       You can  also  use  libbson  as  a  static  library  instead:  Use  the
51       mongo::bson_static CMake target:
52
53          # Specify the minimum version you require.
54          find_package (bson-1.0 1.7 REQUIRED)
55
56          # The "hello_bson.c" sample program is shared among four tests.
57          add_executable (hello_bson ../../hello_bson.c)
58          target_link_libraries (hello_bson PRIVATE mongo::bson_static)
59
60
61   pkg-config
62       If  you're  not  using CMake, use pkg-config on the command line to set
63       header and library paths:
64
65          gcc -o hello_bson hello_bson.c $(pkg-config --libs --cflags libbson-1.0)
66
67
68       Or to statically link to libbson:
69
70          gcc -o hello_bson hello_bson.c $(pkg-config --libs --cflags libbson-static-1.0)
71
72

CREATING A BSON DOCUMENT

74   The bson_t structure
75       BSON documents are created using the bson_t structure.  This  structure
76       encapsulates the necessary logic for encoding using the BSON Specifica‐
77       tion. At the core, bson_t is a buffer manager and set of encoding  rou‐
78       tines.
79
80       TIP:
81          BSON  documents  can live on the stack or the heap based on the per‐
82          formance needs or preference of the consumer.
83
84       Let's start by creating a new BSON document on the stack. Whenever  us‐
85       ing libbson, make sure you #include <bson/bson.h>.
86
87          bson_t b;
88
89          bson_init (&b);
90
91       This creates an empty document. In JSON, this would be the same as {}.
92
93       We  can  now proceed to adding items to the BSON document. A variety of
94       functions prefixed with bson_append_ can be used based on the  type  of
95       field you want to append. Let's append a UTF-8 encoded string.
96
97          bson_append_utf8 (&b, "key", -1, "value", -1);
98
99       Notice  the  two  -1 parameters. The first indicates that the length of
100       key in bytes should be  determined  with  strlen().  Alternatively,  we
101       could  have  passed  the number 3. The same goes for the second -1, but
102       for value.
103
104       Libbson provides macros to make this less  tedious  when  using  string
105       literals. The following two appends are identical.
106
107          bson_append_utf8 (&b, "key", -1, "value", -1);
108          BSON_APPEND_UTF8 (&b, "key", "value");
109
110       Now  let's  take  a  look at an example that adds a few different field
111       types to a BSON document.
112
113          bson_t b = BSON_INITIALIZER;
114
115          BSON_APPEND_INT32 (&b, "a", 1);
116          BSON_APPEND_UTF8 (&b, "hello", "world");
117          BSON_APPEND_BOOL (&b, "bool", true);
118
119       Notice that we omitted the call to bson_init(). By specifying BSON_INI‐
120       TIALIZER  we  can remove the need to initialize the structure to a base
121       state.
122
123   Sub-Documents and Sub-Arrays
124       To simplify the creation of sub-documents and arrays, bson_append_docu‐
125       ment_begin()  and bson_append_array_begin() exist. These can be used to
126       build a sub-document using the parent documents memory  region  as  the
127       destination buffer.
128
129          bson_t parent;
130          bson_t child;
131          char *str;
132
133          bson_init (&parent);
134          bson_append_document_begin (&parent, "foo", 3, &child);
135          bson_append_int32 (&child, "baz", 3, 1);
136          bson_append_document_end (&parent, &child);
137
138          str = bson_as_canonical_extended_json (&parent, NULL);
139          printf ("%s\n", str);
140          bson_free (str);
141
142          bson_destroy (&parent);
143
144          { "foo" : { "baz" : 1 } }
145
146   Simplified BSON C Object Notation
147       Creating  BSON  documents  by  hand  can be tedious and time consuming.
148       BCON, or BSON C Object Notation, was added to allow for the creation of
149       BSON documents in a format that looks closer to the destination format.
150
151       The  following  example  shows  the use of BCON. Notice that values for
152       fields are wrapped in the BCON_* macros. These  are  required  for  the
153       variadic processor to determine the parameter type.
154
155          bson_t *doc;
156
157          doc = BCON_NEW ("foo",
158                          "{",
159                          "int",
160                          BCON_INT32 (1),
161                          "array",
162                          "[",
163                          BCON_INT32 (100),
164                          "{",
165                          "sub",
166                          BCON_UTF8 ("value"),
167                          "}",
168                          "]",
169                          "}");
170
171       Creates the following document
172
173          { "foo" : { "int" : 1, "array" : [ 100, { "sub" : "value" } ] } }
174

HANDLING ERRORS

176   Description
177       Many  libbson functions report errors by returning NULL or -1 and fill‐
178       ing out a bson_error_t structure with an error domain, error code,  and
179       message.
180
181error.domain names the subsystem that generated the error.
182
183error.code is a domain-specific error type.
184
185error.message describes the error.
186
187       Some  error codes overlap with others; always check both the domain and
188       code to determine the type of error.
189
190
191
192
193
194
195
196
197
198
199      ┌──────────────────┬─────────────────────┬────────────────────────────────┐
200BSON_ERROR_JSON   BSON_JSON_ER‐       bson_json_reader_t             
201      │                  │ ROR_READ_CORRUPT_JS │ tried  to parse in‐            │
202      │                  │ BSON_JSON_ER‐       │ valid  MongoDB  Ex‐            │
203      │                  │ ROR_READ_IN‐        │ tended JSON.  Tried            │
204      │                  │ VALID_PARAM         │ to  parse  a  valid            │
205      │                  │ BSON_JSON_ER‐       │ JSON  document that            │
206      │                  │ ROR_READ_CB_FAILURE │ is invalid as  Mon‐            │
207      │                  │                     │ goDBExtended  JSON.            │
208      │                  │                     │ An  internal  call‐            │
209      │                  │                     │ back failure during            │
210      │                  │                     │ JSON parsing.                  │
211      ├──────────────────┼─────────────────────┼────────────────────────────────┤
212BSON_ERROR_READER BSON_ER‐            bson_json_reader_new_from_file 
213      │                  │ ROR_READER_BADFD    │ could not open  the            │
214      │                  │                     │ file.                          │
215      └──────────────────┴─────────────────────┴────────────────────────────────┘
216

OBJECTIDS

218       Libbson  provides a simple way to generate ObjectIDs. It can be used in
219       a single-threaded or multi-threaded manner depending on  your  require‐
220       ments.
221
222       The  bson_oid_t  structure  represents  an ObjectID in MongoDB. It is a
223       96-bit identifier.
224
225   Composition
226       • 4 bytes : The UNIX timestamp in big-endian format.
227
228       • 5 bytes : A random number.
229
230       • 3 bytes : A 24-bit monotonic  counter  incrementing  from  rand()  in
231         big-endian.
232
233   Sorting ObjectIDs
234       The  typical way to sort in C is using qsort(). Therefore, Libbson pro‐
235       vides a qsort() compatible callback function named  bson_oid_compare().
236       It  returns less than 1, greater than 1, or 0 depending on the equality
237       of two bson_oid_t structures.
238
239   Comparing Object IDs
240       If you simply want to compare two bson_oid_t structures  for  equality,
241       use bson_oid_equal().
242
243   Generating
244       To generate a bson_oid_t, you may use the following.
245
246          bson_oid_t oid;
247
248          bson_oid_init (&oid, NULL);
249
250   Parsing ObjectID Strings
251       You  can  also parse a string containing a bson_oid_t. The input string
252       MUST be 24 characters or more in length.
253
254          bson_oid_t oid;
255
256          bson_oid_init_from_string (&oid, "123456789012345678901234");
257
258          bson_oid_t oid;
259
260          bson_oid_init_from_string_unsafe (&oid, "123456789012345678901234");
261
262   Hashing ObjectIDs
263       If you need to store items in a hashtable, you  may  want  to  use  the
264       bson_oid_t  as  the key. Libbson provides a hash function for just this
265       purpose. It is based on DJB hash.
266
267          unsigned hash;
268
269          hash = bson_oid_hash (oid);
270
271   Fetching ObjectID Creation Time
272       You can easily fetch the time that a  bson_oid_t  was  generated  using
273       bson_oid_get_time_t().
274
275          time_t t;
276
277          t = bson_oid_get_time_t (oid);
278          printf ("The OID was generated at %u\n", (unsigned) t);
279

PARSING AND ITERATING BSON DOCUMENTS

281   Parsing
282       BSON  documents are lazily parsed as necessary. To begin parsing a BSON
283       document, use one of the provided Libbson functions  to  create  a  new
284       bson_t  from existing data such as bson_new_from_data(). This will make
285       a copy of the data so that additional mutations may occur to  the  BSON
286       document.
287
288       TIP:
289          If you only want to parse a BSON document and have no need to mutate
290          it, you may use bson_init_static() to avoid making  a  copy  of  the
291          data.
292
293          bson_t *b;
294
295          b = bson_new_from_data (my_data, my_data_len);
296          if (!b) {
297             fprintf (stderr, "The specified length embedded in <my_data> did not match "
298                              "<my_data_len>\n");
299             return;
300          }
301
302          bson_destroy (b);
303
304       Only two checks are performed when creating a new bson_t from an exist‐
305       ing buffer. First, the document must  begin  with  the  buffer  length,
306       matching what was expected by the caller. Second, the document must end
307       with the expected trailing \0 byte.
308
309       To parse the document further we use a bson_iter_t to iterate the  ele‐
310       ments  within  the  document. Let's print all of the field names in the
311       document.
312
313          bson_t *b;
314          bson_iter_t iter;
315
316          if ((b = bson_new_from_data (my_data, my_data_len))) {
317             if (bson_iter_init (&iter, b)) {
318                while (bson_iter_next (&iter)) {
319                   printf ("Found element key: \"%s\"\n", bson_iter_key (&iter));
320                }
321             }
322             bson_destroy (b);
323          }
324
325       Converting a document to JSON uses a bson_iter_t and bson_visitor_t  to
326       iterate  all fields of a BSON document recursively and generate a UTF-8
327       encoded JSON string.
328
329          bson_t *b;
330          char *json;
331
332          if ((b = bson_new_from_data (my_data, my_data_len))) {
333             if ((json = bson_as_canonical_extended_json (b, NULL))) {
334                printf ("%s\n", json);
335                bson_free (json);
336             }
337             bson_destroy (b);
338          }
339
340   Recursing into Sub-Documents
341       Libbson provides convenient sub-iterators to dive down into a sub-docu‐
342       ment  or sub-array. Below is an example that will dive into a sub-docu‐
343       ment named "foo" and print it's field names.
344
345          bson_iter_t iter;
346          bson_iter_t child;
347          char *json;
348
349          if (bson_iter_init_find (&iter, doc, "foo") &&
350              BSON_ITER_HOLDS_DOCUMENT (&iter) && bson_iter_recurse (&iter, &child)) {
351             while (bson_iter_next (&child)) {
352                printf ("Found sub-key of \"foo\" named \"%s\"\n",
353                        bson_iter_key (&child));
354             }
355          }
356
357   Finding Fields using Dot Notation
358       Using   the    bson_iter_recurse()    function    exemplified    above,
359       bson_iter_find_descendant()  can find a field for you using the MongoDB
360       style path notation such as "foo.bar.0.baz".
361
362       Let's create a document like {"foo": {"bar": [{"baz: 1}]}}  and  locate
363       the "baz" field.
364
365          bson_t *b;
366          bson_iter_t iter;
367          bson_iter_t baz;
368
369          b =
370             BCON_NEW ("foo", "{", "bar", "[", "{", "baz", BCON_INT32 (1), "}", "]", "}");
371
372          if (bson_iter_init (&iter, b) &&
373              bson_iter_find_descendant (&iter, "foo.bar.0.baz", &baz) &&
374              BSON_ITER_HOLDS_INT32 (&baz)) {
375             printf ("baz = %d\n", bson_iter_int32 (&baz));
376          }
377
378          bson_destroy (b);
379
380   Validating a BSON Document
381       If  all  you  want to do is validate that a BSON document is valid, you
382       can use bson_validate().
383
384          size_t err_offset;
385
386          if (!bson_validate (doc, BSON_VALIDATE_NONE, &err_offset)) {
387             fprintf (stderr,
388                      "The document failed to validate at offset: %u\n",
389                      (unsigned) err_offset);
390          }
391
392       See the bson_validate() documentation for more  information  and  exam‐
393       ples.
394

UTF-8

396   Encoding
397       Libbson  expects  that  you are always working with UTF-8 encoded text.
398       Anything else is invalid API use.
399
400       If you should need to walk through UTF-8 sequences,  you  can  use  the
401       various UTF-8 helper functions distributed with Libbson.
402
403   Validating a UTF-8 Sequence
404       To  validate  the string contained in my_string, use the following. You
405       may pass -1 for the string length if you know the string is NULL-termi‐
406       nated.
407
408          if (!bson_utf8_validate (my_string, -1, false)) {
409             printf ("Validation failed.\n");
410          }
411
412       If  my_string  has  NULL  bytes within the string, you must provide the
413       string length. Use the following format. Notice the true at the end in‐
414       dicating \0 is allowed.
415
416          if (!bson_utf8_validate (my_string, my_string_len, true)) {
417             printf ("Validation failed.\n");
418          }
419
420       For more information see the API reference for bson_utf8_validate().
421

AUTHOR

423       MongoDB, Inc
424
426       2017-present, MongoDB, Inc
427
428
429
430
4311.20.0                           Nov 18, 2021                 BSON_TUTORIAL(3)
Impressum