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: hello_bson.c.INDENT 0.0
12
13          #include <stdio.h>
14          #include <bson/bson.h>
15
16          int
17          main (int argc, const char **argv)
18          {
19             bson_t *b;
20             char *j;
21
22             b = BCON_NEW ("hello", BCON_UTF8 ("bson!"));
23             j = bson_as_canonical_extended_json (b, NULL);
24             printf ("%s\n", j);
25
26             bson_free (j);
27             bson_destroy (b);
28
29             return 0;
30          }
31
32
33   CMake
34       The libbson installation includes a CMake config-file package,  so  you
35       can  use  CMake's find_package command to import libbson's CMake target
36       and link to libbson (as a shared library): CMakeLists.txt.INDENT 0.0
37
38          # Specify the minimum version you require.
39          find_package (bson-1.0 1.7 REQUIRED)
40
41          # The "hello_bson.c" sample program is shared among four tests.
42          add_executable (hello_bson ../../hello_bson.c)
43          target_link_libraries (hello_bson PRIVATE mongo::bson_shared)
44
45
46You  can  also  use  libbson  as   a   static   library   instead:   Use   the

mongo::bson_static CMake target:

48
49          # Specify the minimum version you require.
50          find_package (bson-1.0 1.7 REQUIRED)
51
52          # The "hello_bson.c" sample program is shared among four tests.
53          add_executable (hello_bson ../../hello_bson.c)
54          target_link_libraries (hello_bson PRIVATE mongo::bson_static)
55
56
57   pkg-config
58       If  you're  not  using CMake, use pkg-config on the command line to set
59       header and library paths:
60
61          gcc -o hello_bson hello_bson.c $(pkg-config --libs --cflags libbson-1.0)
62
63
64       Or to statically link to libbson:
65
66          gcc -o hello_bson hello_bson.c $(pkg-config --libs --cflags libbson-static-1.0)
67
68

CREATING A BSON DOCUMENT

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

HANDLING ERRORS

172   Description
173       Many  libbson functions report errors by returning NULL or -1 and fill‐
174       ing out a bson_error_t structure with an error domain, error code,  and
175       message.
176
177       · error.domain names the subsystem that generated the error.
178
179       · error.code is a domain-specific error type.
180
181       · error.message describes the error.
182
183       Some  error codes overlap with others; always check both the domain and
184       code to determine the type of error.
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199┌──────────────────┬────────────────────────────────────┬────────────────────────────────┐
200BSON_ERROR_JSON   BSON_JSON_ERROR_READ_COR‐          bson_json_reader_t             
201│                  │ RUPT_JS                            │ tried    to   parse            │
202│                  │ BSON_JSON_ERROR_READ_INVALID_PARAM │ invalid     MongoDB            │
203│                  │ BSON_JSON_ERROR_READ_CB_FAIL‐      │ Extended      JSON.            │
204│                  │ URE                                │ Tried  to  parse  a            │
205│                  │                                    │ valid JSON document            │
206│                  │                                    │ that is invalid  as            │
207│                  │                                    │ MongoDBExtended                │
208│                  │                                    │ JSON.  An  internal            │
209│                  │                                    │ callback    failure            │
210│                  │                                    │ during  JSON  pars‐            │
211│                  │                                    │ ing.                           │
212├──────────────────┼────────────────────────────────────┼────────────────────────────────┤
213BSON_ERROR_READER BSON_ERROR_READER_BADFD            bson_json_reader_new_from_file 
214│                  │                                    │ could not open  the            │
215│                  │                                    │ file.                          │
216└──────────────────┴────────────────────────────────────┴────────────────────────────────┘
217

OBJECTIDS

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

PARSING AND ITERATING BSON DOCUMENTS

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

UTF-8

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

AUTHOR

424       MongoDB, Inc
425
427       2017-present, MongoDB, Inc
428
429
430
431
4321.16.2                           Feb 25, 2020                 BSON_TUTORIAL(3)
Impressum