BSON_GUIDES(3)

NAME
bson_guides - Guides

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;
}

USE VALGRIND TO CHECK FOR BSON DATA LEAKS

A stack-allocated bson_t contains a small internal buffer; it only heap-allocates additional storage if necessary, depending on its data size. Therefore if you forget to call bson_destroy() on a stack-allocated bson_t, it might or might not cause a leak that can be detected by valgrind during testing.

To catch all potential BSON data leaks in your code, configure the BSON_MEMCHECK flag:

cmake -DCMAKE_C_FLAGS="-DBSON_MEMCHECK -g" .

With this flag set, every bson_t mallocs at least one byte. Run your program's unittests with valgrind to verify all bson_t structs are destroyed.

Set the environment variable MONGOC_TEST_VALGRIND to on to skip timing-dependent tests known to fail with valgrind.

AUTHOR
MongoDB, Inc

COPYRIGHT
2017-present, MongoDB, Inc