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  find libbson's header and
36       library paths and link to libbson: CMakeLists.txt.INDENT 0.0
37
38          # Specify the minimum version you require.
39          find_package (libbson-1.0 1.7 REQUIRED)
40
41          message ("--   libbson found version \"${BSON_VERSION}\"")
42          message ("--   libbson include path \"${BSON_INCLUDE_DIRS}\"")
43          message ("--   libbson libraries \"${BSON_LIBRARIES}\"")
44
45          # The "hello_bson.c" sample program is shared among four tests.
46          add_executable (hello_bson ../../hello_bson.c)
47          target_include_directories (hello_bson PRIVATE ${BSON_INCLUDE_DIRS})
48          target_link_libraries (hello_bson PRIVATE ${BSON_LIBRARIES})
49          target_compile_definitions (hello_bson PRIVATE ${BSON_DEFINITIONS})
50
51
52By default, libbson is dynamically linked. You can use  libbson  as  a  static
53library  instead:  Use the included libbson-static-1.0 config-file package and
54(on Unix) link to pthread:
55
56          # Specify the minimum version you require.
57          find_package (libbson-static-1.0 1.7 REQUIRED)
58
59          message ("--   libbson-static found version \"${BSON_STATIC_VERSION}\"")
60          message ("--   libbson-static include path \"${BSON_STATIC_INCLUDE_DIRS}\"")
61          message ("--   libbson-static libraries \"${BSON_STATIC_LIBRARIES}\"")
62
63          # The "hello_bson.c" sample program is shared among four tests.
64          add_executable (hello_bson ../../hello_bson.c)
65          target_include_directories (hello_bson PRIVATE ${BSON_STATIC_INCLUDE_DIRS})
66          target_link_libraries (hello_bson PRIVATE ${BSON_STATIC_LIBRARIES})
67          target_compile_definitions (hello_bson PRIVATE ${BSON_STATIC_DEFINITIONS})
68
69
70   pkg-config
71       If you're not using CMake, use pkg-config on the command  line  to  set
72       header and library paths:
73
74          gcc -o hello_bson hello_bson.c $(pkg-config --libs --cflags libbson-1.0)
75
76
77       Or to statically link to libbson:
78
79          gcc -o hello_bson hello_bson.c $(pkg-config --libs --cflags libbson-static-1.0)
80
81

CREATING A BSON DOCUMENT

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

HANDLING ERRORS

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

OBJECTIDS

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

PARSING AND ITERATING BSON DOCUMENTS

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

UTF-8

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

AUTHOR

428       MongoDB, Inc
429
431       2017-present, MongoDB, Inc
432
433
434
435
4361.14.0                           Feb 22, 2019                 BSON_TUTORIAL(3)
Impressum