BSON_GUIDES(3)

STREAMING BSON

bson_reader_t provides a streaming reader which can be initialized with a filedescriptor or memory region. bson_writer_t provides a streaming writer which can be initialized with a memory region. (Streaming BSON to a file descriptor is not yet supported.)

  Reading from a BSON Stream

bson_reader_t provides a convenient API to read sequential BSON documents from a file-descriptor or memory buffer. The bson_reader_read() function will read forward in the underlying stream and return a bson_t that can be inspected and iterated upon.

            #include <stdio.h>
            #include <bson/bson.h>

            int
            main (int argc, char *argv[])
            {
               bson_reader_t *reader;
               const bson_t *doc;
               bson_error_t error;
               bool eof;

               reader = bson_reader_new_from_file ("mycollection.bson", &error);

               if (!reader) {
                  fprintf (stderr, "Failed to open file.\n");
                  return 1;
               }

               while ((doc = bson_reader_read (reader, &eof))) {
                  char *str = bson_as_canonical_extended_json (doc, NULL);
                  printf ("%s\n", str);
                  bson_free (str);
               }

               if (!eof) {
                  fprintf (stderr,
                           "corrupted bson document found at %u\n",
                           (unsigned) bson_reader_tell (reader));
               }

               bson_reader_destroy (reader);

               return 0;
            }

See bson_reader_new_from_fd(), bson_reader_new_from_file(), and bson_reader_new_from_data() for more information.

  Writing a sequence of BSON Documents

bson_writer_t provides a convenient API to write a sequence of BSON documents to a memory buffer that can grow with realloc(). The bson_writer_begin() and bson_writer_end() functions will manage the underlying buffer while building the sequence of documents.

This could also be useful if you want to write to a network packet while serializing the documents from a higher level language, (but do so just after the packets header).

            #include <stdio.h>
            #include <bson/bson.h>
            #include <assert.h>

            int
            main (int argc, char *argv[])
            {
               bson_writer_t *writer;
               bson_t *doc;
               uint8_t *buf = NULL;
               size_t buflen = 0;
               bool r;
               int i;

               writer = bson_writer_new (&buf, &buflen, 0, bson_realloc_ctx, NULL);

               for (i = 0; i < 10000; i++) {
                  r = bson_writer_begin (writer, &doc);
                  assert (r);

                  r = BSON_APPEND_INT32 (doc, "i", i);
                  assert (r);

                  bson_writer_end (writer);
               }

               bson_free (buf);

               return 0;
            }

See bson_writer_new() for more information.

JSON

Libbson provides routines for converting to and from the JSON format. In particular, it supports the MongoDB extended JSON format.

  Converting BSON to JSON

There are often times where you might want to convert a BSON document to JSON. It is convenient for debugging as well as an interchange format. To help with this, Libbson contains the functions bson_as_canonical_extended_json() and bson_as_relaxed_extended_json(). The canonical format preserves BSON type information for values that may have ambiguous representations in JSON (e.g. numeric types).

            bson_t *b;
            size_t len;
            char *str;

            b = BCON_NEW ("a", BCON_INT32 (1));

            str = bson_as_canonical_extended_json (b, &len);
            printf ("%s\n", str);
            bson_free (str);

            bson_destroy (b);

            { "a" : { "$numberInt": "1" } }

The relaxed format prefers JSON primitives for numeric values and may be used if type fidelity is not required.

            bson_t *b;
            size_t len;
            char *str;

            b = BCON_NEW ("a", BCON_INT32 (1));

            str = bson_as_relaxed_extended_json (b, &len);
            printf ("%s\n", str);
            bson_free (str);

            bson_destroy (b);

            { "a" : 1 }

  Converting JSON to BSON

Converting back from JSON is also useful and common enough that we added bson_init_from_json() and bson_new_from_json().

The following example creates a new bson_t from the JSON string {"a":1}.

            bson_t *b;
            bson_error_t error;

            b = bson_new_from_json ("{\"a\":1}", -1, &error);

            if (!b) {
               printf ("Error: %s\n", error.message);
            } else {
               bson_destroy (b);
            }

  Streaming JSON Parsing

Libbson provides bson_json_reader_t to allow for parsing a sequence of JSON documents into BSON. The interface is similar to bson_reader_t but expects the input to be in the MongoDB extended JSON format.

            /*
             * Copyright 2013 MongoDB, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *   http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */

            /*
             * This program will print each JSON document contained in the provided files
             * as a BSON string to STDOUT.
             */

            #include <bson/bson.h>
            #include <stdlib.h>
            #include <stdio.h>

            int
            main (int argc, char *argv[])
            {
               bson_json_reader_t *reader;
               bson_error_t error;
               const char *filename;
               bson_t doc = BSON_INITIALIZER;
               int i;
               int b;

               /*
                * Print program usage if no arguments are provided.
                */
               if (argc == 1) {
                  fprintf (stderr, "usage: %s FILE...\n", argv[0]);
                  return 1;
               }

               /*
                * Process command line arguments expecting each to be a filename.
                */
               for (i = 1; i < argc; i++) {
                  filename = argv[i];

                  /*
                   * Open the filename provided in command line arguments.
                   */
                  if (0 == strcmp (filename, "-")) {
                     reader = bson_json_reader_new_from_fd (STDIN_FILENO, false);
                  } else {
                     if (!(reader = bson_json_reader_new_from_file (filename, &error))) {
                        fprintf (
                           stderr, "Failed to open \"%s\": %s\n", filename, error.message);
                        continue;
                     }
                  }

                  /*
                   * Convert each incoming document to BSON and print to stdout.
                   */
                  while ((b = bson_json_reader_read (reader, &doc, &error))) {
                     if (b < 0) {
                        fprintf (stderr, "Error in json parsing:\n%s\n", error.message);
                        abort ();
                     }

                     if (fwrite (bson_get_data (&doc), 1, doc.len, stdout) != doc.len) {
                        fprintf (stderr, "Failed to write to stdout, exiting.\n");
                        exit (1);
                     }
                     bson_reinit (&doc);
                  }

                  bson_json_reader_destroy (reader);
                  bson_destroy (&doc);
               }

               return 0;
            }

  Examples

The following example reads BSON documents from stdin and prints them to stdout as JSON.

            /*
             * Copyright 2013 MongoDB, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             *   http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             */

            /*
             * This program will print each BSON document contained in the provided files
             * as a JSON string to STDOUT.
             */

            #include <bson/bson.h>
            #include <stdio.h>

            int
            main (int argc, char *argv[])
            {
               bson_reader_t *reader;
               const bson_t *b;
               bson_error_t error;
               const char *filename;
               char *str;
               int i;

               /*
                * Print program usage if no arguments are provided.
                */
               if (argc == 1) {
                  fprintf (stderr, "usage: %s [FILE | -]...\nUse - for STDIN.\n", argv[0]);
                  return 1;
               }

               /*
                * Process command line arguments expecting each to be a filename.
                */
               for (i = 1; i < argc; i++) {
                  filename = argv[i];

                  if (strcmp (filename, "-") == 0) {
                     reader = bson_reader_new_from_fd (STDIN_FILENO, false);
                  } else {
                     if (!(reader = bson_reader_new_from_file (filename, &error))) {
                        fprintf (
                           stderr, "Failed to open \"%s\": %s\n", filename, error.message);
                        continue;
                     }
                  }

                  /*
                   * Convert each incoming document to JSON and print to stdout.
                   */
                  while ((b = bson_reader_read (reader, NULL))) {
                     str = bson_as_canonical_extended_json (b, NULL);
                     fprintf (stdout, "%s\n", str);
                     bson_free (str);
                  }

                  /*
                   * Cleanup after our reader, which closes the file descriptor.
                   */
                  bson_reader_destroy (reader);
               }

               return 0;
            }

BSON_T LIFETIMES

A bson_t may contain its data directly or may contain pointers to heap-allocated memory. Overwriting an existing bson_t or allowing a stack-allocated bson_t to go out of scope may cause a memory leak. A bson_t should always be destroyed with bson_destroy().

  bson_t out parameters

A bson_t pointer used as an out parameter must point to valid overwritable storage for a new bson_t which must be one of:

    1.  Uninitialized storage for a bson_t.

    2.  A zero-initialized bson_t object.

    3.  A bson_t object initialized with BSON_INITIALIZER.

    4.  A bson_t object not created with bson_new() that was destroyed with bson_destroy().

This can be on the stack:

            bson_t stack_doc = BSON_INITIALIZER;
            example_get_doc (&stack_doc);
            bson_destroy (&stack_doc);

Or on the heap:

            bson_t *heap_doc = bson_malloc (sizeof (bson_t));
            example_get_doc (heap_doc);
            bson_destroy (heap_doc);
            bson_free (heap_doc);

Omitting bson_destroy() in either case may cause memory leaks.

WARNING:
        Passing a bson_t pointer obtained from bson_new() as an out parameter will result in a leak of the bson_t struct.

                    bson_t *heap_doc = bson_new ();
                    example_get_doc (heap_doc);
                    bson_destroy (heap_doc); // Leaks the `bson_t` struct!

AUTHOR
MongoDB, Inc

COPYRIGHT
2017-present, MongoDB, Inc