1BSON_TUTORIAL(3) libbson BSON_TUTORIAL(3)
2
3
4
6 bson_tutorial - Tutorial
7
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
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
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
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┌──────────────────┬────────────────────────────────────┬────────────────────────────────┐
200│BSON_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├──────────────────┼────────────────────────────────────┼────────────────────────────────┤
213│BSON_ERROR_READER │ BSON_ERROR_READER_BADFD │ bson_json_reader_new_from_file │
214│ │ │ could not open the │
215│ │ │ file. │
216└──────────────────┴────────────────────────────────────┴────────────────────────────────┘
217
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
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
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
424 MongoDB, Inc
425
427 2017-present, MongoDB, Inc
428
429
430
431
4321.16.2 Feb 25, 2020 BSON_TUTORIAL(3)